Bulk Create or Fixing Personal Sites after Migration/Upgrade

I was involved in many projects where we were upgrading different versions of SharePoint environments to SharePoint 2013.  Most of the content migration was done using Database attach process.  We have migration servers where content databases are being upgrade from 2007 to 2010 and 2010 to 2013.  During the migration many users try to access their personal sites which are replaced by upgraded sites from old versions.  Additionally during testing many users see their personal sites are showing “We are working for  you” or unable to open the site at all becuase their user id is migrated from old domain to new domain. 

Some users reported that although their personal site exist but they were unable to see and post any newsfeeds.  Once I review I found the feed url of some of the profiles were either empty or wrong.  Some users were not owners of their personal sites as their user names were changed.

Step 1 was to export and review all users profiles so that junk profiles and mysites can be removed.  I write a script that can iterate through the profiles and try to make a decision if profile has any of the issues.  Once the profiles were identitfied I used to fix them in small chunks.  But later I was told to fix this issue and for over 50,000 users profiles and my sites.  Customer also requested that the my sites of users must be created in advanced before the launch.  I personal feel that it is not a great idea but as company is launching a large social platform around newsfeed and mysites, I had to do it.  The script to achieve all that is below.  Use it as as needed.  It cover most scanario but please test it in labs before running it on production. 

The average time to create personal site during busy working day was 6 minutes but during weekend changed to 1 minute.   The script can be stoped and started by removing all the entries before the last one manually.  I have not implemented any such logic to start automatically at last step.  The script uses transcript so you can review how many profiles fails to fix or personal sites failed.

CSV Format : Save the Final.CSV which has the following format.
AccountName,PropertyName,UserName
Domain\User1,PropertyValue,User1

Add-PSSnapIn "Microsoft.SharePoint.Powershell" -ErrorAction SilentlyContinue
$FileName = "C:\CreatePersonalSitesBulk\CreatePersonalSiteTranscript" + (Get-Date).tostring("dd-MM-yyyy-hh-mm-ss") + ".txt"
Start-Transcript -Path $FileName

$NewMySiteCount = 0
$MySiteProcessed = 0

$ContextSiteUrl = "https://mysites.contoso.com"
$site = new-object Microsoft.SharePoint.SPSite($ContextSiteUrl);  
$ServiceContext = [Microsoft.SharePoint.SPServiceContext]::GetContext($site);  
$ProfileManager = new-object Microsoft.Office.Server.UserProfiles.UserProfileManager($ServiceContext);  

Write-Output "`nUser Profile Context Loaded Successfully"
$Data = Import-Csv -Path 'C:\CreatePersonalSitesBulk\Final.csv'
Write-Output "`nCSV Imported Sucessfully..."

if($Data)
{
    foreach($aUser in $Data)
    {
         $GlobalStartDate=GET-DATE
         [string]$AccountName = $aUser.AccountName
         $UserName = $aUser.UserName
         $CountryCode = $aUser.CountryCode
         if($AccountName)
         {
            Write-Output "`n************************************************"
            Write-Output "`nCurrent User is $AccountName"
            Write-Output "Sleeping for 5 Seconds..."
            try
            {
                $CurrentProfile = $ProfileManager.GetUserProfile($AccountName);
            }
            catch
            {
                try
                {
                    Write-Output "`nTry to Grab the Profile from Profile Store Again!. Cover the Timeout"
                    $CurrentProfile = $ProfileManager.GetUserProfile($AccountName);
                }
                catch
                {
                    $CurrentProfile = $null
                }
            }
            if($CurrentProfile -ne $null)
            {
                Write-Output "`nUser Profile Exit in Profile Store..."
                $AccountName = $CurrentProfile["AccountName"].Value
                Write-Output "`nReading Account Name from Profile... $AccountName"
                Write-Output "`nChecking If Personal Site Exist in Profile..."
                $PersonalSite = $CurrentProfile.PersonalSite
                $aStartDate=GET-DATE
                if($PersonalSite -ne $null)
                {
                    Write-Output "`nPersonal Site Does Exists in Profile with URL: $PersonalSite"
                    Write-Output "`nChecking for Feed Identifier..."
                    $FeedUrl = $CurrentProfile.FeedIdentifier
                    if($FeedUrl -ne $null)
                    {
                        Write-Output "`nFeed Url is not empty so Skipping to Next Profile."
                        Write-Output "`nPersonal Space Url" 
                        Write-Output $CurrentProfile[[Microsoft.Office.Server.UserProfiles.PropertyConstants]::PersonalSpace].Value
                        Write-Output "Feed Url Exist : $FeedUrl "
                        Write-Output "All Looks Good. so Skipping this user" 
                    }
                    else
                    {
                        Write-Output "`nFeed Url is empty so creating the Url..."
                        $microFeedId = ($PersonalSite.Url + ";1." + $PersonalSite.ID.ToString().Replace("-", "") + "." + $PersonalSite.RootWeb.ID.ToString().Replace("-", "") + "." + $PersonalSite.RootWeb.Lists["Microfeed"].ID.ToString().Replace("-", "") + ".0c37852b34d0418e91c62ac25af4be5b")
                        $CurrentProfile["SPS-FeedIdentifier"].Value = $microFeedId
                        $CurrentProfile.Commit()
                        Write-Output "`nFeed Url is is Updated to Profile..."
                    }
                    Write-Output "`nPersonal Site Object is Disposed..."
                    $PersonalSite.Dispose()
                    $MySiteProcessed +=1
                    $anEndDate=GET-DATE
                    $anGlobalTimeSpan = NEW-TIMESPAN –Start $aStartDate –End $anEndDate
                    Write-Output "My Sites Processed Complete : $NewMySiteCount : Profiles Processed Count : $MySiteProcessed : TIme Take for $UserName is : $anGlobalTimeSpan"
                }
                else
                {
                    Write-Output "`nPersonal Site is not linked to User Profile... Now Checking if MySite Exists..."
                    $MySiteUrl = $ContextSiteUrl + "/personal/$UserName"
                    Write-Output "`nMy Site Url will be  $MySiteUrl"
                    $MSite = Get-SPSite $MySiteUrl -ErrorAction SilentlyContinue
                    if($MSite -ne $null)
                    {
                        Write-Output "`nMy Site is not null so updating User Profile PersonalSpace property..."
                        $CurrentProfile[[Microsoft.Office.Server.UserProfiles.PropertyConstants]::PersonalSpace].Value = ""
                        $CurrentProfile[[Microsoft.Office.Server.UserProfiles.PropertyConstants]::PersonalSpace].Value = "/personal/$UserName"
                        Write-Output "`nCheck FeedIdentifier property for the Profile..."
                        $FeedUrl = $CurrentProfile.FeedIdentifier
                        if($FeedUrl -eq $null)
                        {
                            Write-Output "`nCheck FeedIdentifier is empty..."
                            $microFeedId = ($MSite.Url + ";1." + $MSite.ID.ToString().Replace("-", "") + "." + $MSite.RootWeb.ID.ToString().Replace("-", "") + "." + $MSite.RootWeb.Lists["Microfeed"].ID.ToString().Replace("-", "") + ".0c37852b34d0418e91c62ac25af4be5b")
                            Write-Output "`nCreating and Setting the Feed Identifier..."
                            $CurrentProfile["SPS-FeedIdentifier"].Value = $microFeedId
                        }
                        $CurrentProfile.Commit()
                        Write-Output "`nProfile updates has been commited..."
                        
                        try
                        {
                            Set-SPSite -Identity $MSite -OwnerAlias $AccountName -ErrorAction SilentlyContinue
                            Write-Output "`nProfil User Added As Ownere..."
                        }
                        catch [Exception]
                        {}
                        Write-Output "`nDisposing MySite Object..."
                        $MSite.Dispose()
                        Write-Output "`nProfile properties Personal Space and feed has been updated."
                        $MySiteProcessed +=1
                        Write-Output "My Sites Processed Complete : $NewMySiteCount : Profiles Processed Count : $MySiteProcessed"
                    }
                    else
                    {
                          Write-Output "`nPersonal Site is Null...Creating Personal Site..."
                          try
                          {
                               $StartDate=GET-DATE
                               $CurrentProfile.CreatePersonalSite()
                               $EndDate=GET-DATE
                               $TimeSpan = NEW-TIMESPAN –Start $StartDate –End $EndDate
                               Write-Output "`nFirst Time Personal Site has been Created Successfully in ... $TimeSpan"
                               $NewMySiteCount += 1
                               $MySiteProcessed +=1
                          }
                          catch 
                          {
                            $ErrorMessage = $_.Exception.Message
                            $FailedItem = $_.Exception.ItemName
                            Write-Output $ErrorMessage
                            Write-Output $_.Exception.ToString()
                            Write-Output "`nPersonal Site Creation has failed for User..." $AccountName
                            Write-Output "`nException Occured. Tyring One more Time after refresh."
                            try
                            {
                                $CurrentProfile[[Microsoft.Office.Server.UserProfiles.PropertyConstants]::PersonalSpace].Value = ""
                                $CurrentProfile.Commit()
                                $StartDate=GET-DATE
                                $CurrentProfile.CreatePersonalSite()
                                $TimeSpan = NEW-TIMESPAN –Start $StartDate –End $EndDate
                                 Write-Output "`n2nd Try Personal Site has been Created Successfully in ... $TimeSpan"
                                $NewMySiteCount += 1
                                $MySiteProcessed +=1
                            }
                            catch 
                            {
                                $ErrorMessage = $_.Exception.Message
                                $FailedItem = $_.Exception.ItemName                           
                                Write-Output "`nException Occured in 2nd Attempt for $AccountName...Skipping it."
                                $CurrentProfile[[Microsoft.Office.Server.UserProfiles.PropertyConstants]::PersonalSpace].Value = ""
                                $CurrentProfile.Commit()
                            }

                           
                          }
                          $GlobalEndDate=GET-DATE
                          $GlobalTimeSpan = NEW-TIMESPAN –Start $GlobalStartDate –End $GlobalEndDate
                          Write-Output "My Sites Created Count: $NewMySiteCount : MySite Processed Count : $MySiteProcessed : TIme Take for $UserName is : $GlobalTimeSpan"
                          Write-Output "`n************************************************"
                    }
                    Write-Output "`n************************************************"
                    
                }
            }
            else
            {
                Write-Output "User Profile Does not Exist for $AccountName"
            }
         }
    }
}
Stop-Transcript
Advertisements

4 thoughts on “Bulk Create or Fixing Personal Sites after Migration/Upgrade

  1. Jerry – just wanted to thank you for posting this solution. I rarely comment on blogs, but this post deserves a high five 🙂 Well done sir – portions of this post solved an issue I was troubleshooting with a client that I could not find documented answers for anywhere else. Cheers. C.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s