Monday, April 23, 2012

Display Name in SharePoint is out of synch

In some SharePoint installations there is often a problem with display names of users. As an example: The display name of a user in an organization consists of his firstname surname and orginizational unit like:
  • Betty Looser (RD/F)
If Betty gets married and changes her unit, SharePoint should show her new name and unit
  • Betty Winner (FR/I)
but it displays still the old one. More worse in some sitecollections the name is displayed correctly whereas in others not.

Why is this happening ?

This happens because SharePoint stores all user, which were ever logged in a site collection in a special database table "UserInfo Table". This information is stored for every site collection.
The contents of this table are displayed by a hidden SharePoint list called "User Information List". If you are a SharePoint admin, you can display the list information by typing the following url:
  • http://{sitecollection url}/_catalogs/users/simple.apx
When you first visit a SharePoint site collection, your user info is stored in the database table.

But there is a property in the user info table named "tp_IsActive". This property is set when a user in a site collection gets active. "Active" means (from msdn)

"A user is considered "active" if he or she created or modified any data in the site collection."

This property is used by the SharePoint timer jobs, to synch the user information with the profile store. A user information with tp_IsActive = 0 is therefore never updated within a site collection.

That means all user, that have only read rights or have never changed content in a site collection will have the problem with not updated user display names. This problem is also often caused when you grant "All autheticated users" read rights to a site.

Solution

The solution for this problem is to create a PowerShell script and a Windows Task Schedule.

The PowerShell Script

Create a file and name it "UpdateDisplayName.ps1". The script loops throught all user within all sitecollections and checks if their user display name is different that in profile store. If so the user display name is updated. You can change this script easily to change also other properties.


#
# Author: I.B.Bikmaz
#

# Loading Microsoft.SharePoint.PowerShell
$snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.Powershell'}
if ($snapin -eq $null) {  
  Add-PSSnapin "Microsoft.SharePoint.Powershell"
}

# Loading Needed Assemblies
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") | out-null
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server") | out-null
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server.UserProfiles") | out-null


<# --------------------------------
  These values can be changed
-------------------------------- #>
# -- Format of the date for the log file
# --
$date = Get-Date -uformat "%Y_%m_%d_%H_%M"

# -- Name of the log file
# -- Create Folder if not exists
$log = "E:\Appl\SP2010\Scripts\UserDisplayNameUpdate_$date.log" 

# -- Url of the web application
# --
$webapp = Get-SPWebApplication "http://sharepoint/"

# -----------END CHANGE-----------
  
  
# Logging!! 
Start-Transcript -path $log 

# Write Starting Date
$processDate = Get-Date
Write-Host "Starting Profile Info Update:" $processDate

# Create the stopwatch
[System.Diagnostics.Stopwatch] $sw;
$sw = New-Object System.Diagnostics.StopWatch
$sw.Start()

<# --------------------------------
  GET ProfilService
-------------------------------- #>
$upm = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager( [Microsoft.Office.Server.ServerContext]::Default )
if ($upm -eq $null){
  Write-Host "Could not find User Profile Manager!"
  exit
}

<# --------------------------------
  Looping through all sites 
  to check if stored user info 
  has changed.
-------------------------------- #>
try {  
  foreach($site in $webapp.Sites) {
    $web = $site.RootWeb
    $siteCollUsers = $web.SiteUsers
    
    Write-Host "> SiteCollection: " $site.Url
    
    foreach( $user in $siteCollUsers ) {  
      $login = $user.LoginName                    
      $dispname = $user.Name
      
      if ($upm.UserExists($login)){
        $profile = $upm.GetUserProfile($login);
        $profilename = $profile["PreferredName"].ToString();
        if ($dispname -ne $profilename){
          Write-Host "  >> Changing '" $dispname "' >> '" $profilename "'"
          $user.Name = $profilename
          $user.Update()
        }          
      }
      
    }
    $web.Dispose()
    $site.Dispose()
  }
}
catch [System.Exception] {
  $_.Exception.ToString();
  Write-Host "Error while updating user info tables."
  Stop-Transcript
  exit
} 
  
$sw.Stop()
Write-Host "Time Elapsed: " $sw.Elapsed.ToString()
Write-Host "User Display Names successfully updated !"
Stop-Transcript

The Windows Task Scheduler

Check the script manually before creating a task schedule. Run the script as SharePoint Farm Account or the account which has admin rights on the user profile service. If you use another user the script will fail.

Open the Task Scheduler in Windows 2008 and create a new task. I think that it will be enough to trigger the task once a week (depens on how many user your company has). Run the task as SharePoint Farm Admin or the account which has rights to use the user profile service.

In the Actions tab choose "Start a program" as Action. Program/script is "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" 
and argument is:
-command "C:\Scripts\UpdateDisplayName.ps1"

As the script writes a log file you can check if the script runned successfully. The place for the log file can be changed in the script.










5 comments:

Anonymous said...

I have created a script which syncs all of the properties in the User Information List to the User Profile Service.
It can be found here http://www.softlanding.ca/Blog/Lists/Posts/Post.aspx?ID=46

Anonymous said...

Thank you very much for posting this. This behavior afflicted me a long time and I had no clue about the reason.

Rhygar said...

Awesome!

Anonymous said...

It works fine in the development environment, but I have problems in test/QA. I get an error which states that there aren't any User Profile Applications available.
Do you have a hint that might solve the problem? I can see in CA that User Profile service is started and running.

Baris Bikmaz said...

If the profile service is running, than this can be a permission problem. Give your account enough rights on the user profile service application and try again.