Partager via


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.