Thursday, November 21, 2013

SharePoint PowerShell: A roundabout approach to mysites cleanup Part I

I had a situation where the company mysites cleanup job was turned off, and we needed a manual process to:
1. Detect mysites whose users who are no longer active in AD (Active Directory)
2. Update the site owner to someone else
3. Delete the user profile (to clean up organizational chart)
4. Remove/archive the mysite after x days.

Practically all articles on the WWW on this topic was to adopt an approach using the UserProfileManager to detect users removed from AD. However, this approach did NOT address my particular need.

This approach assumes that:
1. ALL of your mysites follows the same naming convention e.g. http://mysites/personal/username
2. The inactive users were either (1) totally removed; or (2)still in AD, but was moved to a separate OU (Organizational Unit)

For now, let's focus on detecting mysites where users are no longer active.


First you need a function that queries AD:
 #---------------------------------------------------------------------------------  
 # Function to Check if an User exists in AD  
 #---------------------------------------------------------------------------------  
 function CheckUserExistsInAD()  
   {  
   Param( [Parameter(Mandatory=$true)] [string]$UserLoginID )  
  #Cleanup ID  
  $UserLoginID = $UserLoginID -replace "DOMAIN\\", ""  
  #Search the User in AD  
  $forest = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()  
  foreach ($Domain in $forest.Domains)  
  {  
   $context = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext("Domain", $Domain.Name)  
      $domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($context)  
   $root = $domain.GetDirectoryEntry()  
      $search = [System.DirectoryServices.DirectorySearcher]$root  
      $search.Filter = "(&(objectCategory=User)(samAccountName=$UserLoginID))"  
      $result = $search.FindOne()  
      if ($result -ne $null)  
      {   
   $s = $result.path  
       $s = $s.substring($s.indexOf("OU=")+3).split(",")  
   if ($s[0] -like "*Disabled User*")  
   {  
     return $false  
   }  
   #Write-Host "Organizational Unit:" $s[0]  
       return $true  
      }  
  }  
  return $false   
  }  

Now for the action. Load the sharepoint powershell module.
 #Add SharePoint PowerShell SnapIn if not already added  
 if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) {  
   Add-PSSnapin "Microsoft.SharePoint.PowerShell"  
 }  

This step is optional. Create a file for logging.
 # Create Log File  
 $LogDirectory = "D:\Logs"  
 $LogFile = "CleanupUserProfile_" + (Get-Date -UFormat "%Y%m%d") + ".txt"  
 $LogPath = $LogDirectory +"\" + $LogFile  
 if([IO.Directory]::Exists($LogDirectory))   
 {  
 }  
 else   
 {  
   New-Item $LogDirectory -type directory  
 }  
 New-Item $LogPath -type file -force  
 # Write Headers  
 Add-Content $LogPath "Status,MySiteUrl,PrimarySiteOwner,SecondarySiteOwner,Account,Manager"  

Next load all site collections from the mysites web application and loop through each site.
Parse the User ID from the site URL and call the function CheckUserExistsInAD() to make sure the user is valid
 $web = Get-SPWebApplication http://mysites   
 foreach($site in $web.Sites)  
 {  
  if ($site.Url -like "*/personal/*")  
  {  
  #Check original user, and owner is still with the company  
  $MySiteUrl = $site.Url  
  $UserID = $MySiteUrl.substring($MySiteUrl.indexOf("/personal/")+10)  
  $primaryOwner = $site.Owner  
  $secondaryContact = $site.SecondaryContact  
  Write-Host "Mysites: " $UserID  
  #Get manager  
  try {   
   $ServiceContext = [Microsoft.SharePoint.SPServiceContext]::GetContext($site)   
   #Get UserProfileManager from the My Site Host Site context  
   $ProfileManager = new-object Microsoft.Office.Server.UserProfiles.UserProfileManager($ServiceContext)   
    $profile = $ProfileManager.GetUserProfile($UserID)   
    $manager = $profile.GetManager()  
   $ManagerID = $manager[[Microsoft.Office.Server.UserProfiles.PropertyConstants]::AccountName].Value  
   #$ManagerID = $ManagerID -replace "DOMAIN\\", ""  
  } catch {   
   $ManagerID = ""   
  }  
  $blnUserExists = CheckUserExistsInAD($UserID)  
  $blnOwnerExists = CheckUserExistsInAD($primaryOwner)  
  if ([string]::IsNullOrEmpty($secondaryContact)) { $blnSecondaryOwnerExists = $false }  
  else { $blnSecondaryOwnerExists = CheckUserExistsInAD($secondaryContact) }  
  $CurrStatus = "Active"  
  #If user is marked for deletion  
  if (!$blnUserExists)  
  {  
   Write-Host "Tagged for deletion" -foregroundcolor "magenta"  
   $blnUpdateRequired = $false  
   $CurrStatus = "Inactive"   
   $OwnerID = ""  
   $SecondaryContactID = ""  
   Write-Host "Primary Owner:" $primaryOwner $blnOwnerExists  
   Write-Host "Secondary Owner:" $secondaryContact $blnSecondaryOwnerExists  
   #If primary owner is already newowner, double check manager is the secondary owner  
   if ($primaryOwner -contains "DOMAIN\newowner" -and $secondaryContact -contains $ManagerID)   
   {  
   # No update action required  
   }  
        else  
   {  
   $blnUpdateRequired = $true  
   if ([string]::IsNullOrEmpty($ManagerID)){ $blnManagerExists = $false }  
   else { $blnManagerExists = CheckUserExistsInAD($ManagerID) }  
   Write-Host "Manager:" $ManagerID $blnManagerExists  
   $UserIDTmp = "DOMAIN\" + $UserID  
   #Write-Host "|"$UserIDTmp"|"$primaryOwner"|"  
   #If Manager (or someone else) is primary owner, switch them to secondary and assign primary to spadmin  
   if ($primaryOwner -contains $UserIDTmp)  
   {  
    Write-Host "Reassignment detected." -foreground "cyan"  
    $OwnerID = "DOMAIN\newowner"  
    if ($blnOwnerExists)  
    {  
    Write-Host "Owner account is active, re-assign as secondary contact"  
    $SecondaryContactID = $primaryOwner  
    }   
    elseif ($blnSecondaryOwnerExists)  
    {  
    Write-Host "Secondary owner account is active, remain as secondary contact"  
    $SecondaryContactID = $secondaryContact  
    }  
    elseif ($blnManagerExists)  
    {  
    Write-Host "Manager account is active, assign as secondary contact"  
    $SecondaryContactID = $ManagerID  
    }  
   }  
   else  
   {  
    $OwnerID = "DOMAIN\newowner"  
    if ($blnSecondaryOwnerExists)  
    {  
    Write-Host "Secondary owner account is active, remain as secondary contact"  
    $SecondaryContactID = $secondaryContact  
    }  
    elseif ($blnManagerExists)  
    {  
    Write-Host "Manager account is active, assign as secondary contact"  
    $SecondaryContactID = $ManagerID  
    }  
   }  
   }  
   #Assign ownership  
   if ($blnUpdateRequired)  
   {  
   #Perform the rest of the actions here...   
   }  
   
  }  
  Add-Content $LogPath "$CurrStatus,$MySiteUrl,$primaryOwner,$secondaryOwner,$UserID,$ManagerID"  
  }  
  $site.Dispose()  
 }   



Related Posts Plugin for WordPress, Blogger...