Ilse Van Criekinge's Weblog

Addicted to Microsoft Unified Communications

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

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

  • Comments 22
  • Likes

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
  • Where are the pictures physically stored? In AD, in the db somewhere or in the user's mailbox on the Exchange server?

  • Information is stored in active directory database

    -Ilse

  • 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.

  • 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.

  • @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

  • 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

  • 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

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

  • 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.

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

  • 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

  • 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 (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.

  • Abbas, it still uses the same AD attribute - thumbnailPhoto

  • 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 (300x300 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 (300x300 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;

       }

    }

  • 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

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment