Second Life of a Hungarian SharePoint Geek

August 2, 2015

PowerShell Scripts around the SID

Filed under: Active Directory, Migration, PowerShell, SP 2010 — Tags: , , , — Peter Holpar @ 23:38

If you ever migrated SharePoint users you should be familiar either with the Move-SPUser cmdlet or its predecessor, the migrateuser stsadm operation:

$sourceURL = "http://mysites.company.com"
$web = Get-SPWeb $sourceURL
$user = $web.SiteUsers["domain\jdoe"]
Move-SPUser -Identity $user -NewAlias "newDomain\john.doe" –IgnoreSID

or

stsadm -o migrateuser –oldlogin "domain\jdoe" -newlogin "newDomain\john.doe" -ignoresidhistory

As you see, both method relies on the SID (or on its ignorance), but what is this SID and how can we read its value for our SharePoint or Active Directory users?

Each user in the Active Directory (AD) has a security identifier (SID) that is a unique, immutable identifier, allowing the user to be renamed without affecting its other properties.

Reading the SID of a SharePoint user from PowerShell is so simple as:

$web = Get-SPWeb http://YourSharePoint.com
$user = $web.AllUsers["domain\LoginName"]
$user.Sid

To be able to work with Active Directory from PowerShell, you need of course the Active Directory cmdlets. If your machine has no role in AD, you should install this PowerShell module using the steps described in this post.

Once you have this module installed, and you imported it via “Import-Module ActiveDirectory”, you can read the SID of a user in AD:

$user = Get-ADUser UserLoginNameWithoutDomain -Server YourDomainController.company.com
$user.SID.Value

Where UserLoginNameWithoutDomain is the login name of the user without the domain name, like jdoe in case of domain\jdoe, and YourDomainController.company.com is your DC responsible for the domain of your user.

If you need the SID history from AD as well, it’s a bit complicated. In this case I suggest you to read this writing as well.

$ADQuery = Get-ADObject –Server YourDomainController.company.com`
        -LDAPFilter "(samAccountName=UserLoginNameWithoutDomain )" `
        -Property objectClass, samAccountName, DisplayName, `
        objectSid, sIDHistory, distinguishedname, description, whenCreated |
        Select-Object * -ExpandProperty sIDHistory
$ADQuery | % { 
  Write-Host $_.samAccountName
  Write-Host Domain $_.AccountDomainSid.Value 
  Write-Host SID History
  $_.sIDHistory | % {
    $_.Value     
  }
  Write-Host ——————–
}

Advertisements

Tasks regarding to MySites Migration and Automating them via PowerShell

Filed under: Migration, PowerShell, SP 2010 — Tags: , , — Peter Holpar @ 22:40

Recently we have performed a domain migration for a customer, where we had to migrate the MySites of the users as well. In this blog post I share the relevant PowerShell scripts we used to support the migration.In our case it was a SharePoint 2010 farm, however for SharePoint 2013 you should have the same tasks as well, so hopefully you find the scripts useful.

The user naming convention has been changed during the migration, for example a user John Doe had a login name in the source domain (let’s call it simply domain) like jdoe, he has a new login name john.doe in the target domain (let’s call it newDomain).

As you now, each MySite is a separate site collection under a site collection root (like http://mysites.company.com/personal), the last part of the site collection URL is built based on the login name (for example, it was originally http://mysites.company.com/personal/jdoe). Of course, the customer wanted the MySite URLs to reflect the changes in the login name naming conventions (it should be changed http://mysites.company.com/personal/john.doe)

First, we had to migrate the SharePoint user and its permissions using the Move-SPUser cmdlet:

$sourceURL = "http://mysites.company.com/personal/jdoe"
$web = Get-SPWeb $sourceURL
$user = $web.SiteUsers["domain\jdoe"]
Move-SPUser -Identity $user -NewAlias "newDomain\john.doe" –IgnoreSID

We cannot simply change the URL of the site collection. We have to backup it and restore using the new URL as described in this post and illustrated here:

$sourceURL = "http://mysites.company.com/personal/jdoe"
$targetURL = "http://mysites.company.com/personal/john.doe"

# Location for the backup file
$backupPath = "E:\data\mysite.bak"

Try
{
   # Set the Error Action
   $ErrorActionPreference = "Stop"

  Write-Host "Backing up the Source Site Collection…"-ForegroundColor DarkGreen
  Backup-SPSite $sourceURL -Path $backupPath -force
  Write-Host "Backup Completed!`n"

  # Delete source Site Collection
  Write-Host "Deleting the Source Site Collection…"
  Remove-SPSite -Identity $sourceURL -Confirm:$false
  Write-Host "Source Site Deleted!`n"

  # Restore Site Collection to new URL
  Write-Host "Restoring to Target Site Collection…"
  Restore-SPSite $targetURL -Path $backupPath -Confirm:$false
  Write-Host "Site Restored to Target!`n"

  # Remove backup files
  Remove-Item $backupPath
}
Catch
{
  Write-Host "Operation Failed. Find the Error Message below:" -ForegroundColor Red
  Write-Host $_.Exception.Message -ForegroundColor Red
}
Finally
{
   # Reset the Error Action to Default
   $ErrorActionPreference = "Continue"
}
 
Write-host "Process Completed!"

Of course, we have to change the MySite URL in the user profile properties as well as described here. We used the following script: 

$waUrl = "http://mysites.company.com"
$wa = Get-SPWebApplication -Identity $waUrl

# Create Service Context for User Profile Manager
$context = Get-SPServiceContext $wa.Sites[0]

# Get User Profile Manager instance
$upm = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($context)

# Get the user profile for owner of the personal site
$up = $upm.GetUserProfile("newDomain\john.doe")
$up["PersonalSpace"].Value = "/personal/john.doe"
$up.Commit()

Each user is by default the primary site collection administrator of his own MySite. In my former posts I already discussed how we can change the primary site collection administrator with or without elevated permissions. See this posts for reference to change the account to the one from the new domain.

For example, the simplest version:

$targetURL = "http://mysites.company.com/personal/john.doe"
$siteAdmin = New-Object Microsoft.SharePoint.Administration.SPSiteAdministration($targetURL )
$siteAdmin.OwnerLoginName = "newDomain\john.doe"

February 13, 2014

‘Data is Null’ Error When Runnning stsadm -o enumallwebs

Filed under: Migration, SP 2010, STSADM — Tags: , , — Peter Holpar @ 00:36

Recently I was preparing a SharePoint 2010 to 2013 migration following the steps described here.

One of the steps is to create a reports of customizations via the command:

stsadm -o enumallwebs  -includefeatures -includesetupfiles -includewebparts -includeeventreceivers -includecustomlistview -databasename WSS_Content > C:\temp\enumallwebs.xml

However, in my case the command reported an error:

Data is Null. This method or property cannot be called on Null values.

The generated file contained the XML report broken at tag CustomListViews:

image

I found a few potential errors that one can encounter using the stsadm -o enumallwebs here, but none of these seemed to match my case.

I opened stsadm.exe in Reflector, and looked up the SPEnumAllWebs class and its OutputCustomListViewXml method that is responsible for outputting the customized list views.

The method contains this code:

string format = "SELECT tp_ID, tp_DisplayName, DirName, LeafName, tp_view \r\n FROM WebParts (NOLOCK) \r\n INNER JOIN Docs (NOLOCK)  ON \r\n WebParts.tp_PageUrlID = Docs.Id WHERE \r\n tp_SiteId = ‘{0}’ AND WebId = ‘{1}’ AND\r\n tp_View is NOT NULL";
writer.WriteStartElement("CustomListViews");
using (SqlCommand command = SPSqlCommandFactory.Make(string.Format(CultureInfo.InvariantCulture, format, new object[] { siteId, webId })))
{
   using (SqlDataReader reader = db.SqlSession.ExecuteReader(command))
   {
       while (reader.Read())
       {
           Guid guid = reader.GetGuid(0);
           string str2 = reader.GetString(1);
           string str3 = reader.GetString(2);
           string str4 = reader.GetString(3);

The error was caused by reader.GetString(1), as a few of the related records contained NULL as the value of tp_DisplayName.

The affected records belonged to XsltListViewWebPart views, having no DisplayName attribute defined on pages.

To identify all the affected items, we can use the following SQL query in the related content database:

SELECT tp_ID, tp_DisplayName, DirName, LeafName, tp_view FROM WebParts (NOLOCK) INNER JOIN Docs (NOLOCK) ON WebParts.tp_PageUrlID = Docs.Id WHERE tp_View is NOT NULL AND tp_DisplayName is null and tp_WebPartTypeId = ‘874F5460-71F9-FECC-E894-E7E858D9713E’

Instead of fixing the issue at the database level (that would not be supported) I suggest to open the related page in SharePoint Designer using the URL concatenated from DirName and LeafName in the query above, include the DisplayName attribute in the view as shown below, then save the page.

image

Create a free website or blog at WordPress.com.