PowerShell Tools - Removing Orphaned Users from SharePoint

Here’s a script that will walk through all Site Collections in all Web Applications (i.e. your entire farm) and delete any user from the Site Collection that isn’t in ActiveDirectory anymore.

Note this will not remove them from their user profiles, it just cleans up Site Collections. If you want some great info on how the User Profile service works and the My Site Cleanup Job then check out these resources:

Here’s the code:

[int]$GLOBAL:TotalUsersUpdated = 0;
 
function Check_User_In_ActiveDirectory([string]$LoginName, [string]$domaincnx)
{
    $returnValue = $false
    $strFilter = "(&(|(objectCategory=user)(objectCategory=group))(samAccountName=$LoginName))"
    $objDomain = New-Object System.DirectoryServices.DirectoryEntry($domaincnx)
 
    $objSearcher = New-Object System.DirectoryServices.DirectorySearcher
    $objSearcher.SearchRoot = $objDomain
    $objSearcher.PageSize = 1000
    $objSearcher.Filter = $strFilter
    $objSearcher.SearchScope = "Subtree"
 
    $colResults = $objSearcher.FindAll()
 
    if($colResults.Count -gt 0)
    {
        $returnValue = $true
    }
 
    return $returnValue
}
 
function ListOrphanedUsers([string]$SiteCollectionURL, [string]$mydomaincnx)
{
    [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") > $null
    $site = new-object Microsoft.SharePoint.SPSite($SiteCollectionURL)
    $web = $site.openweb()
 
    Write-Host "SiteCollectionURL:", $SiteCollectionURL
 
    $siteCollUsers = $web.SiteUsers
    Write-host "SiteUsers:", $siteCollUsers.Count
    
    #Create array to hold non-existant users
    $usersToRemove = @()
 
    foreach($MyUser in $siteCollUsers)
    {
        if(($MyUser.LoginName.ToLower() -ne "sharepoint\system") -and 
            ($MyUser.LoginName.ToLower() -ne "nt authority\authenticated users") -and 
            ($MyUser.LoginName.ToLower() -ne "nt authority\local service"))
        {
            $UserName = $MyUser.LoginName.ToLower()
            $Tablename = $UserName.split("\")
            
            $returncheck = Check_User_In_ActiveDirectory $Tablename[1] $mydomaincnx 
            if($returncheck -eq $False)
            {
                Write-Host "User does not exist", $MyUser.LoginName, "on domain"
                $usersToRemove = $usersToRemove + $MyUser.LoginName
                $GLOBAL:TotalUsersUpdated += 1;
            }
        }
    }
    
    foreach($u in $usersToRemove)
    {
        Write-Host "Removing", $u, "from site collection", $SiteCollectionURL
        $siteCollUsers.Remove($u)
    }
 
    $web.Dispose()
    $site.Dispose()
}
 
function ListOrphanedUsersForAllColl([string]$WebAppURL, [string]$DomainCNX)
{
    [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") > $null
 
    $Thesite = new-object Microsoft.SharePoint.SPSite($WebAppURL)
    $oApp = $Thesite.WebApplication
    Write-host "Total Site Collections:", $oApp.Sites.Count
 
    $i = 0
    foreach ($Sites in $oApp.Sites)
    {
        $i = $i + 1
        Write-Host "---------------------------------------"
        Write-host "Collection Number", $i, "of", $oApp.Sites.Count
 
        if($i -gt 0)
        {
            $mySubweb = $Sites.RootWeb
            $TempRelativeURL = $mySubweb.Url
            ListOrphanedUsers $TempRelativeURL $DomainCNX
        }
    }
 
    Write-Host "======================================="
 
}
 
function EnumerateAllSiteColl()
{
    $farm = Get-SPWebApplication | select DisplayName
    foreach($app in $farm)
    {
        $webapp = Get-SPWebApplication | ? {$_.DisplayName -eq $app.DisplayName}
        Write-Host "Web Application:", $webapp.DisplayName
        ListOrphanedUsersForAllColl $webapp.Url "LDAP://DC=ca,DC=util"
        Write-Host
    }
}
 
function StartProcess()
{
    cls
 
    [System.Diagnostics.Stopwatch] $sw;
    $sw = New-Object System.Diagnostics.StopWatch
    $sw.Start()
 
    EnumerateAllSiteColl
 
    $sw.Stop()
 
    write-host "***************************"
    write-host $GLOBAL:TotalUsersUpdated, "users removed in", $sw.Elapsed.ToString()
    write-host "***************************"
}
 
StartProcess


Enjoy!

No Comments