SharePoint 2010, User Profiles and Photos Stored In Active Directory

If you have pictures for your users stored in Active Directory and want to use them in SharePoint 2010's user profiles, you may have endured some amount of annoyance in getting from point A to point B. As great an end-user tool as Microsoft SharePoint is, administration of the environment can be incredibly frustrating. Which is probably great if you are a SharePoint consultant, but not so good when getting the infrastructure in place is just one of your many jobs in a corporate IT setting. Guess which of those describes me (hint: I'm not a consultant).

In SharePoint 2007, displaying photos with user profiles was pretty straightforward.  One common method was to throw a URL where the user's picture was being hosted into one of the extensionAttributes in Active Directory. You then mapped that to the SharePoint user profile's Picture property and voila! Piece of cake.

Now in SharePoint 2010 all of the old user profile stuff gets thrown out the window and instead they have bolted on Microsoft Forefront Identity Manager. I'm all for bulking up the underlying technology even if it adds a certain amount of complexity, but you need to provide similar levels of functionality. No such luck here. The Picture property in 2010 can only be linked to what appear to be binary AD attributes. This seems odd since the SharePoint property is a URL. And while properties can synch both ways now (SharePoint can be used to update Active Directory), the out-of-the-box behavior for Pictures is export only.

This is essentially what Microsoft is telling us that everyone should do:

  • Enable MySites for your enterprise.
  • Allow users to upload their own pictures.
  • These pictures are then resized into three different versions (small, medium and large) and stored in a centralize picture library in the My Sites site collection. (I do like this part.) The URL for the medium sized image is then what is stored in the Pictures property.
  • Allow SharePoint to update Active Directory by storing the image in a binary attribute like thumbnailPhoto.

And that is perfectly fine except for a few problems:

  • For good or ill, we are not interested in setting up an internal Facebook where people put any old picture up whether it is of them, their children or heaven only knows what.
  • We do not want to have to create, communicate and enforce policies simply to address what users are allowed to upload. Particularly items that might fall into that "heaven only knows" category.
  • To get the most useful employee directory for things like People Search, we need a majority of our user profiles to have pictures. The percentage of our users who will be able to figure this out and also take the time to do this is small.

I cannot imagine that this sits well with many Enterprise IT organizations. While seemingly minor, this sidelined my company's move from SharePoint 2007 to 2010 simply because I do not like taking away functionality from my customers.

Life got better with the October 2010 Cumulative Update where we finally got the ability to import into the Picture property.

Then life got worse when they pulled the update back.

A month later, life got better when the update was re-released.

Then life got worse again when the December 2010 Cumulative Update came out and you were no longer able to create a Synchronization Target to an Active Directory when SharePoint's NetBiosDomainNamesEnabled setting was set to "True".

Hope was revived once more when we heard that the February 2011 Cumulative Update fixed this. And once it actually did come out in March 2011, everyone cheered (or at least I did).

Even after all of that, another "gotcha" is that after the picture has been imported, it will not automatically show up on user profile pages, search results and other user listings. As mentioned previously, SharePoint will take the image and create three different sized versions that it stores in a Picture Library of your MySite site-collection. Except this only happens when the following PowerShell command is run:
Update-SPProfilePhotoStore -CreateThumbnailsForImportedPhotos 1 -MySiteHostLocation <URL of MySite web application>
My understanding is that if profile pictures get added or changed after you run this command that they will not be added to the picture library until this command is run again. In other words, there is no completely automated way to make this all work out of the box. (Someone please tell me that I'm wrong.)

But that's enough grousing. You probably want to know how to get this done. Assuming that you already have the User Profile Synchronization service running, you will need to do the following:

  • Install the February 2011 Cumulative Update for SharePoint 2010 (link can be found here).
  • Create an Import property mapping between the Picture property and the attribute in AD where your user picture is being stored (e.g. thumbnailPhoto).
  • Create a PowerShell script (name it something like "CreateUserProfileThumbnails.ps1") and put it somewhere on your SharePoint application server. I typically create a volume for general file storage and I have a "Scripts" folder specifically for things like this. Your script should contain the following two lines (remember to change paths as appropriate for your environment):
    &'C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\CONFIG\POWERSHELL\Registration\sharepoint.ps1'
    Update-SPProfilePhotoStore -CreateThumbnailsForImportedPhotos 1 -MySiteHostLocation <URL of MySite web application>
  • In Task Scheduler, create a new task that runs as the SharePoint Farm account on whatever schedule you feel is appropriate (once a day works for me). Make sure it is set to "run whether user is logged on or not". The following shows the entries for the program/script and the command line arguments:

    -NonInteractive -NoProfile -File F:\Scripts\CreateUserProfileThumbnails.ps1
This should allow you to handle more important tasks, secure in the knowledge that your users' photographs are being automatically updated in all of these systems.

Feel free to comment below if you have problems and I'll do my best to point you in the right direction. And don't be shy to chime in if I have missed something and there is a better way. I would like to provide the best possible solution(s).