Updating SharePoint 2010 User Information
One of my clients recently had an issue where a particularly high profile user (CEO) had their title spelled incorrectly in Active Directory; unfortunately the error wasn’t noticed right away and now, despite changing the information in Active Directory, SharePoint was still showing the wrong title in the People Picker when granting the user rights to a Site Collection. Fortunately I had a partial PowerShell script to fix the issue and just needed to only slightly modify it – you can see the original script on pages 299 and 300 of my book. So before I show the modified script it’s first important to understand the problem and why I needed to use a script and why what I had in the book is somewhat incomplete.
Whenever you grant a user rights to a Site Collection or when that user creates/updates/deletes any item within a Site Collection, an entry for the user will be added to a hidden user information list, if not already there. This “User Information List” is located at http://<SiteCollectionUrl>/_catalogs/users/detail.aspx:

By looking at this list you can see that several key pieces of information are stored here – unfortunately, when you change this information in Active Directory the information stored here is not updated (even after running a full or incremental import via UPS). To complicate matters there is no way to edit the information via the browser, thus the need for a PowerShell script. If you click the user’s name you’ll see the additional properties, including an “Edit Item” option, however, the edit dialog is simply a read-only display of the username, helpful right?:

So let’s first consider the scenario that my book addresses and assume that a user had had their name and/or email address changed. To accommodate this scenario we simply use the Set-SPUser cmdlet along with the -SyncFromAD parameter. The following script is taken directly from my book and simply iterates through all Site Collections and calls the Set-SPUser cmdlet for the provided user:
function Sync-SPUser([string]$userName) { Get-SPSite -Limit All | foreach { $web = $_.RootWeb if ($_.WebApplication.UseClaimsAuthentication) { $claim = New-SPClaimsPrincipal $userName -IdentityType WindowsSamAccountName $user = $web | Get-SPUser -Identity $claim -ErrorAction SilentlyContinue } else { $user = $web | Get-SPUser -Identity $userName -ErrorAction SilentlyContinue } if ($user -ne $null) { $web | Set-SPUser -Identity $user -SyncFromAD } $web.Dispose() $_.Dispose() } }
Before I make any changes to demonstrate this script and the modifications we’ll make to it, let’s first see how my user is currently set in the Site Collection:

And as shown in the People Picker:

Note the “Name”/”Display Name”, “Work e-mail”/”E-Mail”, and “Title” fields.
Now I’ll change these values in Active Directory (make the “p” in my last name capitalized, change the title, and set the email) and then run the script (I saved the script as Sync-SPUser.ps1):

(Note that lowercase “p” is the correct spelling for my name, just in case you were wondering
). Now if we look at the user details in the Site Collection and the People Picker we should see the following:


Notice that the the “Name” / “Display Name” and “Work e-mail” / “E-Mail” fields were updated but not the “Title” field. This is because the Set-SPUser cmdlet and -SyncFromAD parameter only updates these two fields. So how do you update the remaining fields? We simply need to add some code to our function which will grab the SPListItem corresponding to the user from the hidden “User Information List” and then update the corresponding fields manually. The following modified script does this for the “Title” field (note that I’ve changed the function signature to take the title in as a parameter):
function Sync-SPUser([string]$userName, [string]$title) { Get-SPSite -Limit All | foreach { $web = $_.RootWeb if ($_.WebApplication.UseClaimsAuthentication) { $claim = New-SPClaimsPrincipal $userName -IdentityType WindowsSamAccountName $user = $web | Get-SPUser -Identity $claim -ErrorAction SilentlyContinue } else { $user = $web | Get-SPUser -Identity $userName -ErrorAction SilentlyContinue } if ($user -ne $null) { $web | Set-SPUser -Identity $user -SyncFromAD $list = $web.Lists["User Information List"] $query = New-Object Microsoft.SharePoint.SPQuery $query.Query = "<Where><Eq><FieldRef Name='Name' /><Value Type='Text'>$userName</Value></Eq></Where>" foreach ($item in $list.GetItems($query)) { $item["JobTitle"] = $title $item.SystemUpdate() } } $web.Dispose() $_.Dispose() } }
The changes to the original function have been highlighted. Note that the internal field name for the “Title” field is “JobTitle” and that is what we are using to set the Title. Now if we run this modified script we should see the Title field updated:


Okay, so what about the other fields (Department, Mobile Number, etc.)? You can see what fields are available to edit by running the following:

In the preceding example I’m grabbing a specific item (in this case the item corresponding to my user) so that I can see the internal field names in context with the data stored by the field – this helps to make sure that I grab the correct field name (i.e., “JobTitle” vs. “Title”). Now you can just add additional fields to update right before the call to SystemUpdate() – simply follow the pattern established for the title field.
So, add this guy to your script library and you’ll be good to go next time someone changes their name, email, or job title.
-Gary
Check out the books I've contributed to at Amazon.com:
Categories
- Article
- General
- PowerShell Cmdlets
- PowerShell Scripting
- Speaking
- STSADM Commands
- Uncategorized
- Scripts
December 22nd, 2011 - 23:45
There exist a Job called “User Profile Service Application – User Profile to SharePoint Full Synchronization” which runs every hour by default. According to the description of this job, I’m guessing it’s doing exactly what you describe above.
December 23rd, 2011 - 10:30
Yes, you are correct and I should have pointed that out in the post. Unfortunately the job was not working for the client and I’ve yet to be able to see it work in any environment I’ve ever looked at – though I know others have had success with it.
December 23rd, 2011 - 05:58
In some cases we can use third-party web-parts that allows users to update their AD and SharePoint details.
For example HarePoint Self Service even alows to upload profile pictures:
http://www.harepoint.com/Products/HarePointSelfService/Default.aspx
December 23rd, 2011 - 07:33
I want to thank you for this article. I had a problem where a user was added to a site collection and then the user’s name was changed. I didn’t know about the -SyncFromAD switch. This was a huge help!
December 23rd, 2011 - 13:13
Nice article Gary. However, I’m not seeing this issue in my farm. As long as the user is “active” on the site, changes are being pushed correctly from the Profile DB to the site (per the timer job mentioned above). If the user isn’t “active”, meaning they have only visited the site but haven’t done anything, changes aren’t pushed.
December 23rd, 2011 - 13:28
Well, like I said, I’ve just not had luck with that timer job though I know it’s supposed to work. The other thing I failed to mention is that of course if you are running Foundation that timer job won’t exist so there’s no automatic syncing (this is what that -SyncFromAD parameter is really for – Foundation users – I’ve just not had luck with the timer job so this approach works well when I need it). So, if the timer does what you need then fantastic – if not then hopefully this post will help you out
January 4th, 2012 - 07:37
I’m fairly new to SharePoint, and had this same problem. I had a user who had access to the site via AD group permissions. I searched for a solution like this, but being new to SharePoint I ended up manually adding the user to the site with read access, then removing the user (again, allowing her AD permissions to take over). This seemed to re-sync AD and the user information list.
January 19th, 2012 - 11:55
One more idea, we can simply delete the Corresponding User profile from site collection. On his next login the AD information is automatically updated in User Information list.
January 20th, 2012 - 09:05
Just be aware that if you do that then you also delete any permissions assigned directly to the user.
January 20th, 2012 - 12:17
Great post. I have tried to run the script (the second one) and it failed. I did not modify the script, just copied and pasted it. Any ideas? Here is the one of the errors lines:
You cannot call a method on a null-valued expression.
At C:\Users\yassar\Syn-SPUser2.ps1:16 char:39
+ foreach ($item in $list.GetItems <<<< ($query)) {
+ CategoryInfo : InvalidOperation: (GetItems:String) [], RuntimeE
xception
+ FullyQualifiedErrorId : InvokeMethodOnNull
January 20th, 2012 - 15:12
I appears to be failing in getting the hidden user informaiton list – do you have site admin rights to the site?
January 24th, 2012 - 08:51
Thanks Gray. You are the man!!!