evont-software.com

Email: info@evont-software.com

Migrate User Profile My Links

Category:Administration
Date:
Author: Mathias Osterkamp

SharePoint users can store favorite links directly inside the mysite. If you like to migrate to another SharePoint version or different server maybe you like to transfer these links without copy the database. In general these links are stored in the ProfileDB of your server. There is a smart article about this from Vinods source.

Here a small sample, where you can edit links:

mylinks.png


source

Solution

I wrote a improved script to import and export the data via xml. For export we use the profile manager to get the data and collect for every user all links.

1$profileManager = Get-UserProfileManager
2$profiles = $profileManager.GetEnumerator()
3$all = $profileManager.Count
4$collection = @()
5$num = 0
6foreach ($profile in $profiles) {
7 $userProfile = $profileManager.GetUserProfile($profile.AccountName);
8 foreach ($link in $userProfile.QuickLinks.GetItems() ) {
9 $myLink = [PSCustomObject]@{
10 AccountName = $profile.AccountName
11 Title = $link.Title
12 Url = $link.Url
13 Group = $link.Group
14 PrivacyLevel = $link.PrivacyLevel
15 ID = $link.ID
16 }
17 $collection += $myLink
18 }
19 $num ++
20 if (0 -eq ($num % 1000)) {
21 Write-Host "User profiles collected $num / $all" -ForegroundColor Gray
22 }
23}


On the import site we need only recreate this link

1$profileManager = Get-UserProfileManager
2$userProfile = $profileManager.GetUserProfile($link.AccountName);
3$userProfile.QuickLinks.Create($link.Title, $link.Url, "UserSpecified", $link.Group, $link.PrivacyLevel) | Out-Null


Full script:


1Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
2
3Function Export-UserProfileLinks($filePath) {
4 Try {
5 Write-Host "Enter Export-UserProfileLinks"
6 $list = Get-UserProfileLinks
7 #convert to xml
8 $xmlBackup = $list | ConvertTo-FullXML -ObjectName "Link" -RootNodeName "Links"
9 #write file
10 $xmlBackup | Out-File -FilePath $filePath
11 }
12 Catch {
13 throw $_.Exception.Message
14 }
15 Write-Host "Leave Export-UserProfileLinks"
16}
17Function Import-UserProfileLinks($configFilePath) {
18 Try {
19 Write-Host "Enter Import-UserProfileLinks"
20 [xml] $configXml = Get-Content $configFilePath -Encoding UTF8
21 foreach ($link in $configXml.UserProfileLinks.UserProfileLink) {
22 Edit-UserProfileLink $link
23 }
24 }
25 Catch {
26 throw $_.Exception.Message
27 }
28 Write-Host "Leave Import-UserProfileLinks"
29}
30Function Get-UserProfileLinks() {
31 $profileManager = Get-UserProfileManager
32 $profiles = $profileManager.GetEnumerator()
33 $all = $profileManager.Count
34 $collection = @()
35 $num = 0
36 foreach ($profile in $profiles) {
37 $userProfile = $profileManager.GetUserProfile($profile.AccountName);
38 foreach ($link in $userProfile.QuickLinks.GetItems() ) {
39 $myLink = [PSCustomObject]@{
40 AccountName = $profile.AccountName
41 Title = $link.Title
42 Url = $link.Url
43 Group = $link.Group
44 PrivacyLevel = $link.PrivacyLevel
45 ID = $link.ID
46 }
47 $collection += $myLink
48 }
49 $num ++
50 if (0 -eq ($num % 1000)) {
51 Write-Host "User profiles collected $num / $all" -ForegroundColor Gray
52 }
53 }
54 Write-Host "User profiles $num collected"
55 return $collection
56}
57function Edit-UserProfileLink($link) {
58 Try {
59 $profileManager = Get-UserProfileManager
60 $userProfile = $profileManager.GetUserProfile($link.AccountName);
61 $userProfile.QuickLinks.Create($link.Title, $link.Url, "UserSpecified", $link.Group, $link.PrivacyLevel) | Out-Null
62 }
63 Catch {
64 Write-Host "$($link.AccountName) cannot import $($link.Title)" -ForegroundColor DarkYellow
65 }
66}
67function Get-UserProfileManager() {
68 $caURL = (Get-SPWebApplication -IncludeCentralAdministration | Where-Object -FilterScript {
69 $_.IsAdministrationWebApplication -eq $true
70 }).Url
71 $serviceContext = Get-SPServiceContext -Site $caURL
72 return New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($serviceContext);
73}
74function ConvertTo-FullXML {
75 [CmdletBinding()]
76 param (
77 #Object to Input
78 [Parameter(ValueFromPipeline)]$InputObject,
79 #Name of the root document node. Defaults to "Objects"
80 $RootNodeName = "Config",
81 $ObjectName = $null
82 )
83 begin {
84 [xml]$Doc = New-Object System.Xml.XmlDocument
85 #Add XML Declaration
86 $null = $doc.AppendChild($doc.CreateXmlDeclaration("1.0", "UTF-8", $null))
87 #Add XML Root Node
88 $root = $doc.AppendChild($doc.CreateElement($RootNodeName))
89 }
90 process {
91 if ($null -eq $ObjectName) {
92 $elementname = $InputObject.gettype().name
93 }
94 else {
95 $elementname = $ObjectName
96 }
97 $childObject = $doc.CreateElement($elementname)
98 foreach ($propItem in $InputObject.psobject.properties) {
99 $propNode = $doc.CreateElement($propItem.Name)
100 $propNode.InnerText = $propItem.Value
101 $null = $childObject.AppendChild($propNode)
102 }
103 $null = $root.AppendChild($childObject)
104 }
105 end {
106 return $doc.outerxml
107 }
108}


To run with on export server

$file = "c:\temp\profilelinks.xml"
Export-UserProfileLinks $file

And recreate it on import server

$file = "c:\temp\profilelinks.xml"
Import-UserProfileLinks $file

Addition

I like to mention there are also some solution to display these links in modern ui sample or sample 2

Migrate User Profile My Links | Evont Software GmbH | Evont Software GmbH