Upload picture in Outlook 2010 using the Exchange Management Shell (Exchange 2010)


While prepping for one of my sessions @ TechEd Berlin on managing and administering Exchange 2010, I was looking for a demo to illustrate the changes introduced with Remote Powershell  when importing and exporting files. That’s when I stumbled into the Exchange Management Shell cmdlet Import-RecipientDataProperty, which is described in the following TechNet article: Import-RecipientDataProperty.


So here are the steps to get a picture uploaded into Active Directory, in this example my user Ilse doesn’t have a picture yet



Step 1. Get a picture


You need a JPEG file, limited in size to 10 kilobytes!


Step 2. Run the Exchange Management Shell cmdlet Import-RecipientDataProperty


Run the Exchange Management Shell cmdlet to upload the picture. Running it will populate Active Directory with the picture, more specifically the attribute called thumbnailPhoto will be populated. Make sure this attribute is replicated to the Global Catalog (big thank you to Astrid for helping me out with this one :-)) .


Before running the cmdlet, the attribute doesn’t have a value:



 Check if the attribute is replicated to the Global Catalog, by using for example the Schema Snap-In:



Run the following cmdlet:



Few remarks:


– there is no need to refer to a UNC path, you can locate the file anywhere


– remember the limit of 10KB!!


After running this, Active Directory will be populated:



And after restarting Outlook, the picture will be there 🙂



 


-Ilse


Follow-up: If you want to know if this will work with Exchange 2003-Exchange 2007, click this link:


http://blogs.technet.com/ilvancri/archive/2010/01/08/follow-up-import-recipientdataproperty.aspx

Comments (23)

  1. Anonymous says:

    I realize this post was meant more to describe the new tools in Exchange 2010, but this actually alerted me to the fact that this could be done in Exchange 03/07 as well.  However, your domain does have to have the forest prep done for Server 2008 (but does not need any 2008 DC’s).  I discovered this after much head banging with MS beta support.  With those schema additions, Outlook pulls the picture from the thumbnailphoto attribute like a charm.

    Great new Outlook 2010 feature.

  2. Anonymous says:

    I actually got this working in a 2003 Native AD forest without any of the 2008 and up schema extensions. The thumbnailPhoto attribute is there, though I’m not sure what schema update added them. I do have the Exchange 2010 schema updates, so maybe that added them.

    The step I did forget was replicating the attribute to the global catalog. Once I did that, it all worked like a charm.

  3. Anonymous says:

    Hi, where should I start trouble shooting if the thumbnailPhoto attribute is populated and I can export the users photo using powershell but no contact photos are showing in Outlook? Thanks

  4. ntpro says:

    Where are the pictures physically stored? In AD, in the db somewhere or in the user’s mailbox on the Exchange server?

  5. Chris128 says:

    I'm confused… why does every single article on the internet state that this attribute is limited to 10 KB when it is actually 100 KB ? Look at the screenshot in this blog post of the thumbnailPhoto attribute properties and you can see the maximum is 102400 (bytes) which is 100 KB. I thought maybe I was missing something obvious but I just confirmed it by uploading an image into this attribute that was roughly 90 KB – it worked fine. When I tried to upload an image that was 120 KB however it failed with the error  "a constraint violation occurred" which is exactly what you would expect if the attribute is limited to 100 KB.

    I don't know if the powershell cmdlets that come with Exchange 2010 prevent you from actually choosing an image larger than 10 KB though… but if anyone wants a free easy to use GUI program for uploading single or multiple images, I've nearly finished making such a program. You can find more info on my blog here: cjwdev.wordpress.com/…/ad-photo-edit-a-program-for-uploading-images-into-the-active-directory-thumbnailphoto-attribute-used-by-outlook-2010

  6. Anonymous says:

    Thanks for the tip – nice feature, it would be really good if the clients could change this.

    Just a reminder (as it took me a while to remember/find) to set the attribute to sync, first register the schema plugin with "regsvr32 schmmgmt.dll"

    Run mmc, add Active Directory Schema

  7. Anonymous says:

    @ctobio: you dont need a forest prep or anything else to get this work….this works with a native 2003 ad, too. No need to prep

  8. ilvancri says:

    Information is stored in active directory database

    -Ilse

  9. Yavuz Bogazci says:

    Hi, i have developed a GUI application for managing the thumbnailPhoto Attribute, too. You can find it on my blog here: http://www.starcoder.net/thumbnailphoto-tool

  10. Chris128 says:

    Yavuz, I'm a bit disappointed that your app won't even open if you are not running it on a computer that is a member of a domain. I wanted to try it out from my home PC against a test domain over a VPN.

  11. Abbas Calcuttawala says:

    hi, if we implement Outlook 2010 contact picture adding on Exch 2003, does anyone know what attribute in AD will the pics be stored?

  12. Yavuz Bogazci says:

    Chris128, hello Chris thank you for your respond. The reason is, that the tool allows the current logged in user to change his photo or another persons /accounts photo in the ad. That emans the that it tries to connect top the ad with your current credentials. I will have a look for extending the application, so that you provide different credentials to connect to the ad. thank you. best regards Yavuz

  13. Chris128 says:

    Yavuz, yeah if it is a .NET application then it is pretty easy to bind to the domain with different credentials and also let the user specify a domain name themselves. In my AD Photo Edit application (http://www.cjwdev.co.uk/…/Info.html) I try to bind to the user's domain first but have an option to disable this and enter a domain name and credentials of your own – I think its a useful option personally but I guess the majority of people will be running this on the domain they actually want to work with anyway.

  14. Chris128 says:

    Abbas, it still uses the same AD attribute – thumbnailPhoto

  15. Paul Adams says:

    Codez: Updates two attributes so that it also shows up in Cisco Unified Presence as well as Outlook 2010.

    Cheers

    form1.cs

    ——————————————  

    using System;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Data;

    using System.Drawing;

    using System.Linq;

    using System.Text;

    using System.Windows.Forms;

    using System.DirectoryServices;

    namespace WindowsFormsApplication1

    {

       public partial class Form1 : Form

       {

           public Form1()

           {

               InitializeComponent();

           }

           private void button1_Click(object sender, EventArgs e)

           {

               AddPictureToUser("cn=" + txtUserName.Text + "," + txtLDAPString.Text, txtDomainController.Text, txtImageLocation.Text);

           }

           void AddPictureToUser(string strDN, string strDCName, string strFileName )

           {

               try

               {

                   // Open file

                   System.IO.FileStream inFile = new System.IO.FileStream(strFileName, System.IO.FileMode.Open, System.IO.FileAccess.Read);

                   // Retrive Data into a byte array variable

                   byte[] binaryData = new byte[inFile.Length];

                   int bytesRead = inFile.Read(binaryData, 0, (int)inFile.Length);

                   inFile.Close();

                   inFile.Dispose();

                   // Connect to AD

                   System.DirectoryServices.DirectoryEntry myUser = new System.DirectoryServices.DirectoryEntry(@"LDAP://" + strDCName + @"/" + strDN);

                   // Clear existing picture if exists

                   if (myUser.Properties["jpegPhoto"] != null)

                   {

                       myUser.Properties["jpegPhoto"].Clear();

                   }

                   // Update attribute with binary data from file

                   myUser.Properties["jpegPhoto"].Add(binaryData);

                   if (myUser.Properties["thumbnailPhoto"] != null)

                   {

                       myUser.Properties["thumbnailPhoto"].Clear();

                   }

                   myUser.Properties["thumbnailPhoto"].Add(binaryData);

                   myUser.CommitChanges();

                   myUser.Close();

                   myUser.Dispose();

                   binaryData = null;

                   MessageBox.Show("Done!");

               }

               catch (Exception ex)

               {

                   MessageBox.Show("Error: " + ex.Message, "FUUUUU… You are doing it wr-", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Error);

               }

           }

           private void button2_Click(object sender, EventArgs e)

           {

               ofd.ShowDialog();

               if (ofd.FileName.Length > 0)

               {

                   this.txtImageLocation.Text = ofd.FileName;

                   try

                   {

                       this.panel1.BackgroundImage = Image.FromFile(ofd.FileName);

                       this.panel1.BackgroundImageLayout = ImageLayout.Stretch;

                   }

                   catch (Exception ex1)

                   {

                       MessageBox.Show(ex1.ToString());

                   }

               }

           }

       }

    }

    ——————–

    namespace WindowsFormsApplication1

    namespace WindowsFormsApplication1

    {

       partial class Form1

       {

           /// <summary>

           /// Required designer variable.

           /// </summary>

           private System.ComponentModel.IContainer components = null;

           /// <summary>

           /// Clean up any resources being used.

           /// </summary>

           /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>

           protected override void Dispose(bool disposing)

           {

               if (disposing && (components != null))

               {

                   components.Dispose();

               }

               base.Dispose(disposing);

           }

           #region Windows Form Designer generated code

           /// <summary>

           /// Required method for Designer support – do not modify

           /// the contents of this method with the code editor.

           /// </summary>

           private void InitializeComponent()

           {

               this.button1 = new System.Windows.Forms.Button();

               this.txtUserName = new System.Windows.Forms.TextBox();

               this.txtImageLocation = new System.Windows.Forms.TextBox();

               this.label1 = new System.Windows.Forms.Label();

               this.label2 = new System.Windows.Forms.Label();

               this.label3 = new System.Windows.Forms.Label();

               this.txtLDAPString = new System.Windows.Forms.TextBox();

               this.button2 = new System.Windows.Forms.Button();

               this.ofd = new System.Windows.Forms.OpenFileDialog();

               this.panel1 = new System.Windows.Forms.Panel();

               this.label5 = new System.Windows.Forms.Label();

               this.txtDomainController = new System.Windows.Forms.TextBox();

               this.SuspendLayout();

               //

               // button1

               //

               this.button1.Location = new System.Drawing.Point(423, 194);

               this.button1.Name = "button1";

               this.button1.Size = new System.Drawing.Size(75, 23);

               this.button1.TabIndex = 0;

               this.button1.Text = "Save!";

               this.button1.UseVisualStyleBackColor = true;

               this.button1.Click += new System.EventHandler(this.button1_Click);

               //

               // textBox1

               //

               this.txtUserName.Location = new System.Drawing.Point(35, 73);

               this.txtUserName.Name = "textBox1";

               this.txtUserName.Size = new System.Drawing.Size(100, 20);

               this.txtUserName.TabIndex = 1;

               this.txtUserName.Text = "Paul Adams";

               //

               // textBox2

               //

               this.txtImageLocation.Location = new System.Drawing.Point(35, 167);

               this.txtImageLocation.Name = "textBox2";

               this.txtImageLocation.ReadOnly = true;

               this.txtImageLocation.Size = new System.Drawing.Size(229, 20);

               this.txtImageLocation.TabIndex = 2;

               this.txtImageLocation.Text = "pick a jpg";

               //

               // label1

               //

               this.label1.AutoSize = true;

               this.label1.Location = new System.Drawing.Point(21, 57);

               this.label1.Name = "label1";

               this.label1.Size = new System.Drawing.Size(272, 13);

               this.label1.TabIndex = 3;

               this.label1.Text = "Users Name as it appears in active directory (and LDAP)";

               //

               // label2

               //

               this.label2.AutoSize = true;

               this.label2.Location = new System.Drawing.Point(21, 149);

               this.label2.Name = "label2";

               this.label2.Size = new System.Drawing.Size(164, 13);

               this.label2.TabIndex = 4;

               this.label2.Text = "Location of Image (300×300 max)";

               //

               // label3

               //

               this.label3.AutoSize = true;

               this.label3.Location = new System.Drawing.Point(21, 9);

               this.label3.Name = "label3";

               this.label3.Size = new System.Drawing.Size(156, 13);

               this.label3.TabIndex = 6;

               this.label3.Text = "LDAP Location of user account";

               //

               // textBox3

               //

               this.txtLDAPString.Location = new System.Drawing.Point(35, 25);

               this.txtLDAPString.Name = "textBox3";

               this.txtLDAPString.Size = new System.Drawing.Size(264, 20);

               this.txtLDAPString.TabIndex = 5;

               this.txtLDAPString.Text = "ou=users,ou=corporate,dc=corp,dc=ad";

               //

               // button2

               //

               this.button2.Location = new System.Drawing.Point(268, 165);

               this.button2.Name = "button2";

               this.button2.Size = new System.Drawing.Size(28, 23);

               this.button2.TabIndex = 9;

               this.button2.Text = "…";

               this.button2.UseVisualStyleBackColor = true;

               this.button2.Click += new System.EventHandler(this.button2_Click);

               //

               // ofd

               //

               this.ofd.DefaultExt = "jpg";

               this.ofd.FileName = "Picture.jpg";

               this.ofd.InitialDirectory = "c:\";

               //

               // panel1

               //

               this.panel1.BackColor = System.Drawing.Color.Silver;

               this.panel1.Location = new System.Drawing.Point(323, 12);

               this.panel1.Name = "panel1";

               this.panel1.Size = new System.Drawing.Size(175, 175);

               this.panel1.TabIndex = 10;

               //

               // label5

               //

               this.label5.AutoSize = true;

               this.label5.Location = new System.Drawing.Point(21, 101);

               this.label5.Name = "label5";

               this.label5.Size = new System.Drawing.Size(130, 13);

               this.label5.TabIndex = 12;

               this.label5.Text = "Random domain controller";

               //

               // textBox4

               //

               this.txtDomainController.Location = new System.Drawing.Point(35, 117);

               this.txtDomainController.Name = "textBox4";

               this.txtDomainController.Size = new System.Drawing.Size(100, 20);

               this.txtDomainController.TabIndex = 11;

               this.txtDomainController.Text = "DC03";

               //

               // Form1

               //

               this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);

               this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;

               this.ClientSize = new System.Drawing.Size(509, 226);

               this.Controls.Add(this.label5);

               this.Controls.Add(this.txtDomainController);

               this.Controls.Add(this.panel1);

               this.Controls.Add(this.button2);

               this.Controls.Add(this.label3);

               this.Controls.Add(this.txtLDAPString);

               this.Controls.Add(this.label2);

               this.Controls.Add(this.label1);

               this.Controls.Add(this.txtImageLocation);

               this.Controls.Add(this.txtUserName);

               this.Controls.Add(this.button1);

               this.Name = "Form1";

               this.Text = "Picture-ater Gizmo";

               this.ResumeLayout(false);

               this.PerformLayout();

           }

           #endregion

           private System.Windows.Forms.Button button1;

           private System.Windows.Forms.TextBox txtUserName;

           private System.Windows.Forms.TextBox txtImageLocation;

           private System.Windows.Forms.Label label1;

           private System.Windows.Forms.Label label2;

           private System.Windows.Forms.Label label3;

           private System.Windows.Forms.TextBox txtLDAPString;

           private System.Windows.Forms.Button button2;

           private System.Windows.Forms.OpenFileDialog ofd;

           private System.Windows.Forms.Panel panel1;

           private System.Windows.Forms.Label label5;

           private System.Windows.Forms.TextBox txtDomainController;

       }

    }

    {

       partial class Form1

       {

           /// <summary>

           /// Required designer variable.

           /// </summary>

           private System.ComponentModel.IContainer components = null;

           /// <summary>

           /// Clean up any resources being used.

           /// </summary>

           /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>

           protected override void Dispose(bool disposing)

           {

               if (disposing && (components != null))

               {

                   components.Dispose();

               }

               base.Dispose(disposing);

           }

           #region Windows Form Designer generated code

           /// <summary>

           /// Required method for Designer support – do not modify

           /// the contents of this method with the code editor.

           /// </summary>

           private void InitializeComponent()

           {

               this.button1 = new System.Windows.Forms.Button();

               this.txtUserName = new System.Windows.Forms.TextBox();

               this.txtImageLocation = new System.Windows.Forms.TextBox();

               this.label1 = new System.Windows.Forms.Label();

               this.label2 = new System.Windows.Forms.Label();

               this.label3 = new System.Windows.Forms.Label();

               this.txtLDAPString = new System.Windows.Forms.TextBox();

               this.button2 = new System.Windows.Forms.Button();

               this.ofd = new System.Windows.Forms.OpenFileDialog();

               this.panel1 = new System.Windows.Forms.Panel();

               this.label5 = new System.Windows.Forms.Label();

               this.txtDomainController = new System.Windows.Forms.TextBox();

               this.SuspendLayout();

               //

               // button1

               //

               this.button1.Location = new System.Drawing.Point(423, 194);

               this.button1.Name = "button1";

               this.button1.Size = new System.Drawing.Size(75, 23);

               this.button1.TabIndex = 0;

               this.button1.Text = "Save!";

               this.button1.UseVisualStyleBackColor = true;

               this.button1.Click += new System.EventHandler(this.button1_Click);

               //

               // textBox1

               //

               this.txtUserName.Location = new System.Drawing.Point(35, 73);

               this.txtUserName.Name = "textBox1";

               this.txtUserName.Size = new System.Drawing.Size(100, 20);

               this.txtUserName.TabIndex = 1;

               this.txtUserName.Text = "Paul Adams";

               //

               // textBox2

               //

               this.txtImageLocation.Location = new System.Drawing.Point(35, 167);

               this.txtImageLocation.Name = "textBox2";

               this.txtImageLocation.ReadOnly = true;

               this.txtImageLocation.Size = new System.Drawing.Size(229, 20);

               this.txtImageLocation.TabIndex = 2;

               this.txtImageLocation.Text = "pick a jpg";

               //

               // label1

               //

               this.label1.AutoSize = true;

               this.label1.Location = new System.Drawing.Point(21, 57);

               this.label1.Name = "label1";

               this.label1.Size = new System.Drawing.Size(272, 13);

               this.label1.TabIndex = 3;

               this.label1.Text = "Users Name as it appears in active directory (and LDAP)";

               //

               // label2

               //

               this.label2.AutoSize = true;

               this.label2.Location = new System.Drawing.Point(21, 149);

               this.label2.Name = "label2";

               this.label2.Size = new System.Drawing.Size(164, 13);

               this.label2.TabIndex = 4;

               this.label2.Text = "Location of Image (300×300 max)";

               //

               // label3

               //

               this.label3.AutoSize = true;

               this.label3.Location = new System.Drawing.Point(21, 9);

               this.label3.Name = "label3";

               this.label3.Size = new System.Drawing.Size(156, 13);

               this.label3.TabIndex = 6;

               this.label3.Text = "LDAP Location of user account";

               //

               // textBox3

               //

               this.txtLDAPString.Location = new System.Drawing.Point(35, 25);

               this.txtLDAPString.Name = "textBox3";

               this.txtLDAPString.Size = new System.Drawing.Size(264, 20);

               this.txtLDAPString.TabIndex = 5;

               this.txtLDAPString.Text = "ou=users,ou=corporate,dc=corp,dc=ad";

               //

               // button2

               //

               this.button2.Location = new System.Drawing.Point(268, 165);

               this.button2.Name = "button2";

               this.button2.Size = new System.Drawing.Size(28, 23);

               this.button2.TabIndex = 9;

               this.button2.Text = "…";

               this.button2.UseVisualStyleBackColor = true;

               this.button2.Click += new System.EventHandler(this.button2_Click);

               //

               // ofd

               //

               this.ofd.DefaultExt = "jpg";

               this.ofd.FileName = "Picture.jpg";

               this.ofd.InitialDirectory = "c:\";

               //

               // panel1

               //

               this.panel1.BackColor = System.Drawing.Color.Silver;

               this.panel1.Location = new System.Drawing.Point(323, 12);

               this.panel1.Name = "panel1";

               this.panel1.Size = new System.Drawing.Size(175, 175);

               this.panel1.TabIndex = 10;

               //

               // label5

               //

               this.label5.AutoSize = true;

               this.label5.Location = new System.Drawing.Point(21, 101);

               this.label5.Name = "label5";

               this.label5.Size = new System.Drawing.Size(130, 13);

               this.label5.TabIndex = 12;

               this.label5.Text = "Random domain controller";

               //

               // textBox4

               //

               this.txtDomainController.Location = new System.Drawing.Point(35, 117);

               this.txtDomainController.Name = "textBox4";

               this.txtDomainController.Size = new System.Drawing.Size(100, 20);

               this.txtDomainController.TabIndex = 11;

               this.txtDomainController.Text = "DC03";

               //

               // Form1

               //

               this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);

               this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;

               this.Client

  16. Paul Adams says:

    email me if you need a working .exe that you can use to accomplish this without powershell or CLI commands. padams at sourcedirect dot com

  17. Javi Miro says:

    I work with Windows 2003, I see that It is necessary register  schmmgmt.dll but I don't  find the dll, somebody can help me?

  18. Gary Levell says:

    We have a free product available from our website that makes this very easy. http://www.exclaimer.com/…/Default.aspx

  19. zack says:

    Exclaimer's Outlook Photo tool is AWESOME! It is a GUI and automatically links up the pictures to the users if the filenames are the same as the usernames! Great!

  20. ISOmir says:

    You can also use this free tool for importing and managing users' Active Directory photos. As shown in this vid:

    http://www.youtube.com/watch

  21. Shafeek says:

    try this free tool, very easy top use, auto image editing and you can import pictures based on different conditions.

    http://www.codetwo.com/…/active-directory-photos

  22. bap says:

    if you already have a 20GB of ntds.dit and adding the photo of arround 2GB. Does it really going to create replication issues from there onwards? Also, if you push nearly 1.5Lakh employees together how about the data write/read going to effect the AD?
    Does it get stored in lync/outlook cache so that it doesnt require to read every time from AD. Really concerned about the ad replication once the db size is more than 21GB. Any suggesion on implimenting the changes on ad which has huge DB size already…

  23. show box says:

    Thanks for the great info. I really loved this. I would like to apprentice at the same time as you amend your web site, how could i subscribe for a blog site?
    For more info on showbox please refer below sites:
    http://showboxandroids.com/showbox-apk/
    http://showboxappandroid.com/
    Latest version of Showbox App download for all android smart phones and tablets.
    http://movieboxappdownloads.com/ – It’s just 2 MB file you can easily get it on your android device without much trouble. Showbox app was well designed application for android to watch movies and TV shows, Cartoons and many more such things on your smartphone.
    For showbox on iOS (iPhone/iPad), please read below articles:
    http://showboxappk.com/showbox-for-ipad-download/
    http://showboxappk.com/showbox-for-iphone/
    Showbox for PC articles:
    http://showboxandroids.com/showbox-for-pc/
    http://showboxappandroid.com/showbox-for-pc-download/
    http://showboxforpcs.com/
    There are countless for PC clients as it is essentially easy to understand, simple to introduce, gives continuous administration, effectively reasonable. it is accessible at completely free of expense i.e., there will be no establishment charges and after establishment
    it doesn’t charge cash for watching films and recordings.
    http://www.showboxforipad.org/showbox-apk/ Not simply watching, it likewise offers alternative to download recordings and motion pictures. The accompanying are the strides that are to be taken after to introduce Showbox application on Android. The above
    all else thing to be done is, go to the Security Settings on your Android telephone, Scroll down and tap on ‘Obscure sources’.
    http://www.showboxforipad.org/
    http://movieboxappdownloads.com/moviebox-apk-android/
    http://movieboxappdownloads.com/download-moviebox-pc/
    Movie Box, an esteemed movies application in which you can find stacks of programs and films. The guide is given here to download Movie Box app to Android and to Apple iOS 9.0.2, iOS 8.4/8.3 and also for the lower versions without Jailbreak.
    http://showboxforiphone.org/
    Please do login to Showbox application with the help of Ymail. You can login in Ymail from here –
    http://ymaillogintips.com/
    Sign Up & Do registration for latest movies on Showbox application