SharePoint 2013: Another way to change order of user profile properties via powershell
I recently ran into an issue where we couldn't change the position of a certain custom user profile property past a certain point.
Looking around the web, I found several resources such as this (Kudos to the author), that provided a way to reorder the profile properties. However, when I looked closer at the default DisplayOrder for existing properties, I noticed several were duplicated.
I have a feeling the duplicate display order values have something with the inability to move properties around through Central admin.
As such, the following solution allows:
- exporting all the properties and sections out to an XML file
- you the Admin, can then clean up the XML, define the order of properties (ie use this mechanism to move properties up and down)
- importing the cleaned up XML
The script is as follows. Just copy and paste into powershell ISE or save as a .ps1 file.
The script will prompt you to select whether you want to Export or Import....pay attention to the prompts. It should be pretty self explanatory.
#This is the xml template into which properties are exported
$template = "
<Properties>
<Section Name="""" Order="""" >
<Property Name="""" Order="""" />
</Section>
</Properties>"
#xml template is saved out
$template | out-file $home\output.xml
$xml = New-Object XML
$xml.Load("$home\output.xml")
#IMPORTANT...fill this section out before executing script
$siteUrl = https://URLtoSiteCollection
function exportProfileProperties()
{
#connect to upa
$site = Get-SPSite $siteUrl
$context = Get-SPServiceContext $site
$psm = [Microsoft.Office.Server.UserProfiles.ProfileSubtypeManager]::Get($context)
$col = $psm.GetSubtypesForProfileType("User")
#load xml template
$sectionTemplate = @($xml.Properties.Section)[0]
$propertyTemplate = @($xml.Properties.Section.Property)[0]
$newSection = ""
#parse sections and properties and generate xml structure
foreach($propFromUPA in $col.PropertiesWithSection)
{
if($propFromUPA.IsSection -eq $true)
{
$newSection = $sectionTemplate.Clone()
$newSection.Name = $propFromUPA.Name
$newSection.Order = $propFromUPA.DisplayOrder.ToString()
$xml.Properties.AppendChild($newSection)
}
else
{
$newProp = $propertyTemplate.Clone()
$newProp.Name = $propFromUPA.Name
$newProp.Order = $propFromUPA.DisplayOrder.ToString()
$newSection.AppendChild($newProp)
}
#cleanup xml
$newSection.Property | where-object{$_.Name -eq ''} | ForEach-Object {$newSection.RemoveChild($_)}
}
#cleanup xml
$xml.Properties.Section | where-object {$_.Name -eq ''} | ForEach-Object {$xml.Properties.RemoveChild($_)}
#save xml
$xml.Save("$home\output2.xml")
write-host "File has been exported to " + "$home\output2.xml"
write-host "Edit the file by updating the display order and the location where you want to property to be"
write-host "Then run this script again to in Import mode"
}
function importProfileProperties($fileLocation)
{
#load xml
$inputXML = [XML] (Get-Content $fileLocation)
#connect to upa
$site = Get-SPSite $siteUrl
$context = Get-SPServiceContext $site
$upcManager = New-Object Microsoft.Office.Server.UserProfiles.UserProfileConfigManager($context)
$defaultUserProfileSubTypeName = [Microsoft.Office.Server.UserProfiles.ProfileSubtypeManager]::GetDefaultProfileName("User")
$profileSubtypePropManager = $upcManager.ProfilePropertyManager.GetProfileSubtypeProperties($defaultUserProfileSubTypeName)
#read entries in xml file
foreach($section in $inputXML.Properties.childnodes)
{
#process sections
Write-Host $section.Name
$profileSubtypePropManager.SetDisplayOrderBySectionName($section.Name,$section.Order)
#process properties within sections
foreach($property in $section.childnodes)
{
Write-Host $property.Name
$profileSubtypePropManager.SetDisplayOrderByPropertyName($property.Name,$property.Order)
}
}
#verify user wants to commit
$commit = Read-Host "Press Y to commit changes or CTRL+C to exit "
if ($commit.ToLower() -eq 'y')
{
$profileSubtypePropManager.CommitDisplayOrder()
}
}
$userInput = Read-Host "Type E to export the current properties OR I to import a config file "
if ($userInput.ToLower() -eq "e")
{
exportProfileProperties
}
elseif($userInput.ToLower() -eq "i")
{
$fileLocation = Read-Host "Type in the path to the input file "
importProfileProperties($fileLocation)
}
Comments
- Anonymous
February 03, 2014
Works fine with SharePoint 2013! Finally a solution for the reordering bug! You are great! Thanks! - Anonymous
February 17, 2014
hey, thanks for this. Great stuff ! - Anonymous
February 27, 2014
Fantastic, many thanks! - Anonymous
April 07, 2014
I cannot get this to work. The error is UserProfileApplication.SqlSession has empty Application ID.
I am new to powershell.
pleaes help - Anonymous
June 17, 2014
I cannot get this to work this either. The error is UserProfileApplication.SqlSession has empty Application ID. It looks like it is unable to get the context although I am giving the correct sharepoint url. - Anonymous
December 01, 2014
Great!! Works like a charm. - Anonymous
June 18, 2015
works great on 2013 thanks! - Anonymous
June 26, 2015
awesome!...I become old just changing the order but looks like you save my life....its works like a charm. do you know if it work for 2010 as well? - Anonymous
July 29, 2015
is no working for I. Plx help.
cannooot get Context or sumthing :@ - Anonymous
December 03, 2015
For the people having I cannot get this to work this either. The error is UserProfileApplication.SqlSession has empty Application ID.
It's a permission issue. You have to add the account running the script in the Full control permissions of the User Profile Service Application - Anonymous
December 03, 2015
For the people having the error : "UserProfileApplication.SqlSession has empty Application ID"
It's a permission issue. You have to add the account running the script in the Full control permissions of the User Profile Service Application. Go th service appliactions highlight the userprofile service app, in the ribbon click on permission search and add the user and check full control.