Powershell Script to find out Orphan Users ( Who are no longer available in AD but SharePoint) in SharePoint 2013

Hi,

Can you please on the above issue? I have one script which works fine for sp2010 but not sp2013 below,

Script

------------------------------------

function Check_User_In_ActiveDirectory([string]$LoginName, [string]$domaincnx)
{
$returnValue = $false
#Filter on User which exists and activated
#$strFilter = "(&(objectCategory=user)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2)(samAccountName=$LoginName))"
#Filter on User which only exists
#$strFilter = "(&(objectCategory=user)(objectClass=user)(samAccountName=$LoginName))"
#Filter on User and NTgroups which only exists
$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"

#$objSearcher.PropertiesToLoad.Add("name")

$colResults = $objSearcher.FindAll()

if($colResults.Count -gt 0)
{
#Write-Host "Account exists and Active: ", $LoginName
$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()

#Debugging - show SiteCollectionURL
write-host "SiteCollectionURL: ", $SiteCollectionURL
Write-Output "SiteCollectionURL - $SiteCollectionURL"

$siteCollUsers = $web.SiteUsers
write-host "Users Items: ", $siteCollUsers.Count

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"))
{
#Write-Host "  USER: ", $MyUser.LoginName
$UserName = $MyUser.LoginName.ToLower()
$Tablename = $UserName.split("\")
Write-Host "User Login: ", $MyUser.LoginName

$returncheck = Check_User_In_ActiveDirectory $Tablename[1] $mydomaincnx 
if($returncheck -eq $False)
{
#Write-Host "User not exist: ",  $MyUser.LoginName, "on domain", $mydomaincnx 
Write-Output $MyUser.LoginName 
}
}
}

$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 of Site Collections: ", $oApp.Sites.Count

$i = 0
foreach ($Sites in $oApp.Sites)
{
$i = $i + 1
write-host "Collection N ", $i, "on ", $oApp.Sites.Count

if($i -gt 0)
{
$mySubweb = $Sites.RootWeb
$TempRelativeURL = $mySubweb.Url
ListOrphanedUsers $TempRelativeURL $DomainCNX
}
    }

}

function StartProcess()
{
# Create the stopwatch
[System.Diagnostics.Stopwatch] $sw;
$sw = New-Object System.Diagnostics.StopWatch
$sw.Start()
#cls

ListOrphanedUsersForAllColl "http://portal" "LDAP://DC=Srabon,DC=com" 
ListOrphanedUsersForAllColl "http://portal/sites/Test" "LDAP://DC=Srabon,DC=com"  


$sw.Stop()

# Write the compact output to the screen
write-host "Time: ", $sw.Elapsed.ToString()
}

StartProcess

# Can be executed with that command : "Check-SharePoint-Orphaned-Users.ps1 > orphaned_users.txt"

--------------------------------------------------------------------

March 28th, 2014 6:08pm

Hi Srabon,

Try this it works in SP2007, SP2010, and SP2013.

Mod line 70: $WebAppURL="http://intranet.contoso.com" to your "http://WebApp"

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
#Functions to Imitate SharePoint 2007, 2010, 2013
function global:Get-SPWebApplication($WebAppURL)

{

return [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup($WebAppURL)

}

function global:Get-SPSite($url)

{

return new-Object Microsoft.SharePoint.SPSite($url)

}

function global:Get-SPWeb($url)

{

$site= New-Object Microsoft.SharePoint.SPSite($url)
if ($site -ne $null)

	{

	$web=$site.OpenWeb();

	}

return $web

}

#Check if User exists in ActiveDirectory
function CheckUserExistsInAD()

{

Param( [Parameter(Mandatory=$true)] [string]$UserLoginID )

#Search the User in ActiveDirectory
$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)

		{

		return $true

		}

	}

	return $false

}

$WebAppURL="http://intranet.contoso.com"

#Get all Site Collections of the web application
$WebApp = Get-SPWebApplication $WebAppURL
		
#Iterate through all Site Collections
foreach($site in $WebApp.Sites)

{

#Get all Webs with Unique Permissions - Which includes Root Webs
$WebsColl = $site.AllWebs | Where {$_.HasUniqueRoleAssignments -eq $True} | ForEach-Object {
$OrphanedUsers = @()

#Iterate through the users collection
foreach($User in $_.SiteUsers)

	{

	#Exclude Built-in User Accounts , Security Groups & an external domain "corporate"
    if (($User.LoginName.ToLower() -ne "nt authority\authenticated users") -and
    ($User.LoginName.ToLower() -ne "sharepoint\system") -and
    ($User.LoginName.ToLower() -ne "nt authority\local service")  -and
    ($user.IsDomainGroup -eq $false ) -and
    ($User.LoginName.ToLower().StartsWith("corporate") -ne $true) )
		
		{

        $UserName = $User.LoginName.split("\")  #Domain\UserName
		$AccountName = $UserName[1]    #UserName
        if ( ( CheckUserExistsInAD $AccountName) -eq $false )

			{
			
			Write-Host "$($User.Name)($($User.LoginName)) from $($_.URL) doesn't Exists in AD!"

			#Display Orphaned users
			$OrphanedUsers+=$User.LoginName

			}

		}

	}
	
	# <<<UNCOMMENT to Remove Users#
	# Remove the Orphaned Users from the site
	# foreach($OrpUser in $OrphanedUsers)
	#   {

	#   $_.SiteUsers.Remove($OrpUser)
	#   Write-host "Removed the Orphaned user $($OrpUser) from $($_.URL) "

	#   }

	}
	
	$web.Dispose()
	$site.Dispose()
	
}

clip_image001 clip_image002 clip_image003 clip_image004 clip_image006 clip_image008

Free Windows Admin Tool Kit Click here and download it now
March 29th, 2014 7:08am

Hi Evan,

Thanks for your reply. Could you please give me a clear instruction about the script in which portion i have to modify as per my environment? Also need to know where the list of orphan users will be saved?

Srabon

March 29th, 2014 11:06pm

Hi Srabon,

Just the $WebAppUR variable

From: $WebAppURL="http://intranet.contoso.com"
To:     $WebAppURL="http://YourWebApp,Domain.com"

I also commented the following two lines to show you the results

    ($User.LoginName.ToLower() -ne "sharepoint\system") -and
   
($User.LoginName.ToLower() -ne "nt authority\local service")  -and

Results:

Results of OrhanedUsers.ps1

Cheers,

clip_image001 clip_image002 clip_image003 clip_image004 clip_image006 clip_image008

Free Windows Admin Tool Kit Click here and download it now
March 30th, 2014 7:56pm

Hi Ivan,

unfortunately the script stopped working, probably after an update but I'm not sure.

Exception calling "Lookup" with "1" argument(s): "This operation can be performed only on a computer that is joined to
a server farm by users who have permissions in SQL Server to read from the configuration database. To connect this serv
er to the server farm, use the SharePoint Products Configuration Wizard, located on the Start menu in Microsoft SharePo
int 2010 Products."
At C:\scriptPath.ps1:6 char:10
+   return [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup($WebAppU ...
+          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : InvalidOperationException

It fails on:

function global:Get-SPWebApplication($WebAppURL)
 { 
  return [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup($WebAppURL)
 }

Any help would be appreciated

March 24th, 2015 4:31pm

Hi,

You have to add modify the $WebAppURL parameter to use your Web Application URL... I used intranet.contoso.com you should be able to search for it...

$WebAppURL="http://intranet.trex-si.com"


-Ivan

Free Windows Admin Tool Kit Click here and download it now
March 27th, 2015 7:05pm

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics