Find and Delete Orphaned Users in SharePoint with PowerShell

Some times back, I posted an article on Orphaned Users in SharePoint. in short, SharePoint orphaned users are those who are deleted from Active Directory, but still have permissions to SharePoint sites!  Read more here: Find and Delete Orphaned Users in SharePoint

find and delete orphaned users in sharepoint

PowerShell to Find and Delete Orphaned Users in SharePoint

Now, with PowerShell, We can Find and Delete orphaned users in SharePoint. Here is the script:

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

#Parameter
$WebAppURL="https://intranet.crescent.com"
 
#Function to Check if a User exists in AD
Function Check-UserExistsInAD()
{
    Param( [Parameter(Mandatory=$true)] [string]$UserLoginID)
    Write-host $UserLoginID
    #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)
        {
           return $true
        }
    }
  return $false  
 }
  
#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 
        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 ) )
                {
                    $UserName = $User.LoginName.split("\")  #Domain\UserName
                    $AccountName = $UserName[1]    #UserName
                    if ( ( Check-UserExistsInAD $AccountName) -eq $false )
                    {
                                Write-Host "$($User.Name)($($User.LoginName)) from $($_.URL) doesn't Exists in AD!"
                                     
                                #Make a note of the Orphaned user
                                $OrphanedUsers+=$User.LoginName
                    }
                }
        }
    }
}
        
# ****  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) "
#   }

Executing this script will scan and give the list of orphaned users in a SharePoint web application. It can be used in SharePoint 2010 also to find & delete orphaned users.

SharePoint orphaned users cleanup:
I’ve commented out the “Remove Users” section at the bottom of the script.  Just remove # tags to uncomment and execute the script to delete orphaned users in SharePoint.

Salaudeen Rajack

Salaudeen Rajack - Information Technology Expert with Two-decades of hands-on experience, specializing in SharePoint, PowerShell, Microsoft 365, and related products. He has held various positions including SharePoint Architect, Administrator, Developer and consultant, has helped many organizations to implement and optimize SharePoint solutions. Known for his deep technical expertise, He's passionate about sharing the knowledge and insights to help others, through the real-world articles!

38 thoughts on “Find and Delete Orphaned Users in SharePoint with PowerShell

  • Sorry. But isn’t there a logical error in the script?
    Doesn’t the code for deleting the users have to be placed within the foreach of the sites so that the orphaned users per site are deleted? Or am I making a mistake?

    Reply
  • SP2016 -The first part of script is OK. But when I am trying to delete orphaned users I got error:
    # **** 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) ”
    }

    Error
    You cannot call a method on a null-valued expression.
    At line:3 char:9 (my note: location after Foreach)
    + $_.SiteUsers.Remove($OrpUser)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Removed the Orphaned user i:0#.w|domanX\userX from site/X

    Reply
  • I am getting below message after running orpahnuser.ps1 script above.I would like to know if we need to pass each user details or it will give all inactive user list.

    cmdlet ForEach-Object at command pipeline position 2
    Supply values for the following parameters:
    Process[0]:

    Reply
  • Hi Salaudeen,

    I have sharepoint 2013 foundation running in my environment, can I use this script ? I am sure that it will not work. can you please help me with creating a new script for finding orphan user were the user profile is not configured.

    Thanks you.

    BR
    MDA

    Reply
  • Hi Salaudeen,

    I have sharepoint 2013 foundation running in my environment, can I use this command to find orphan user, if not then can you help me in this regards, or how can I append this command to find orphan users on the sharepoint site.

    Reply
    • This script doesn’t use User profile service – So should be fine with SharePoint 2013 Foundation as well.

      Reply
  • Can you put this as an attachment on the blog post?

    Copying and pasting from your blog post removes all carriage returns and makes the script unrunable without a half an hour of line break adding.

    Reply
  • what will happen to the documents or list items modified by the now orphan user? the created by and modified field to be specific?

    Reply
    • All documents and List items stays intact – except the created by or modified fields replaced with “System Account”

      Reply
  • What will happen to the document or list items modified by orphan user, will the field get updated with system account?

    Reply
  • I received unexpected token and parser errors on vglnk and wondering if anyone could tell me why and how to fix? Thanks in advance!

    Reply
  • I run this but get the error CheckUserExistsInAD : Cannot bind argument to parameter ‘UserLoginID’ because it is an empty string. Any idea why?

    Reply
  • Anyone else getting an unexpected token or expression error on line 49?

    Reply
  • Hello, I’m very newbie on this part. I want to remove in my SP2010 sites, all users that have been deleted in AD. Can you help me please ? The above code works ? How to run it ? Regards & Thx !

    Reply
    • Hi Serenade,
      1. Change the Web Application URL in Line#49
      2. Uncomment the code between Line#83 to 89
      3. Save and Run the script with PowerShell

      Reply
  • Hello,

    The above script reports deleted users from active directory. Could you please help me in modifying the script to consider both disable and delete users in active directory and compare with sharepoint and output to CSV.

    Thanks in Advance.

    Reply
    • Hello,

      How do i modify the script to consider disable users as well.

      $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
      }

      Above lines of script considers only deleted user and if user is deleted it returns false. But i need for disable users also like if user is disabled (Enabled=false) then it should return false.

      Thanks in Advance.

      Reply
    • Import-Module ActiveDirectory

      #Function to Check if the user account is enabled or not
      Function Check-UserEnabled($LoginID)
      {
      Return Get-ADUser -LDAPFilter “(samaccountname=$LoginID)” | Select-Object -ExpandProperty enabled
      }

      #SamAccountName
      $UserID=”Salaudeen”

      Check-UserEnabled $UserID

      Reply
    • To find all disabled users, use:
      Get-ADUser -Filter {Enabled -eq $false} | FT samAccountName

      Reply
    • Hello,

      Thanks a lot for your response. Could you please let me know how can i modify the above script.

      Above script which you have written in this blog gives me exactly all the details of deleted users and compares with sharepoint. In the same way i need both disable and deleted users to be compared with sharepoint and output to CSV.

      Do i need to change the filter condition in above script (line #43). Please help me.

      Thanks in Advance.

      Reply
  • Is it possible to target the script to only report orphans for a single sub site only? I tried changing AllWebs to RootWeb and changed the URL to the subsite URL, but it still delivers just the Root users/orphans only

    Reply
  • hi thanks for this nice script , it gives normal users who are in AD also as orphaned users in my 2010 SP . Anything wrong ?

    Cheers 🙂
    SA

    Reply
    • The user account which runs this script MUST have Read-Only access at least to AD to retrieve AD objects. Make sure you are able to connect with AD and retrieve user objects from the WFE server runs this script.

      Reply
  • This script was a great starting point. Thanks for sharing.

    Reply
  • The script works fine in check/preview mode and returns lots of oldstaff as expected, but near the end I get lots of errors like this – any idea why?

    The ‘=’ operator failed: Exception has been thrown by the target of an invocation..
    At C:PowershellFindOrphanedUsers.ps1:114 char:13
    + $WebsColl = <<<< $site.AllWebs | Where {$_.HasUniqueRoleAssignments -eq $Tr ue} | ForEach-Object { + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : OperatorFailed

    Reply
  • Hi am getting below error while executing the script “The term ‘CheckUserExistsInAD’ is not recognized as a cmdlet, function, operable program, or script file. Verify the te
    rm and try again.
    At line:18 char:47
    + if ( ( CheckUserExistsInAD <<<< $AccountName) -eq $false ) The term 'CheckUserExistsInAD' is not recognized as a cmdlet, function, operable program, or script file. Verify the te rm and try again. At line:18 char:47" Please suggest , Thanks in advance.

    Reply
  • In line 57 change Allwebs to RootWeb

    I have diffrent sitution is there any way to check againts each DC in AD, we have 5 DC. So in same case Domian1user1 move to Domain2User1. Domain1user1 is removed from AD, but still on site collection as orphan user, but when i run above script it dosnet give me result since it running againts Global AD and looking for Loginname (user1) and user1 is active in Domain2 it not coming back as orphan for USER1 in domain1 ??

    Reply
  • Thanks for Shareing great Script, one quesiton though why its checking all webs for orphan user ?
    I ran this script in my enviroment and it taking while to find orphan user, some all of the are same user at different location. Is there anyway just to check at User Information List where all user reside , to find and delete from there, once you delete from site collection it will be gone from everywhere.

    Reply
  • can we write the output in a csv file? if yes then please share

    Reply
    • Simple! Just use: $User.LoginName | out-file “d:OrphanedUsersRpt.txt” -append after line# 78.

      Reply
    • Great..it worked..You Are The MAN 🙂

      Reply
    • You can also include the User’s full name and URL of where the orphaned account is located, just use: “$($User.Name);$($User.LoginName);$($_.URL)” | out-file “d:OrphanedUsersRpt.txt” -append after line# 78.

      Reply
  • Ya know. Forget I said anything – it works! Just let it sit for a while. Thanks for the awesome script.

    Reply
  • I don’t really understand. I ran this script against 2 developement environements to test – and both times – the script enumerated through the list (e.g. Zenis, Linda(ad9781) from https://stg2-community.com doesn’t Exists in AD! and Zevis, Sophi(ad158) from https://stg2-community.com doesn’t Exists in AD!) but, every time – the script HANGS on “removed orphaned user % from %webapp%.

    I have rebooted , and it STILl does this. I would anticipate it wouldn’t be very time consuming – and i am also getting nothing in the ULS. I am also running as farm account with full rights into UPA. ideas?

    Reply
  • How to change script to remove disabled accounts from AD ? 🙂 Thanks!

    Reply
    • Just change the Filter parameter in the function CheckUserExistsInAD() to:
      (&(objectCategory=person)(objectClass=user)( !(userAccountControl:1.2.840.113556.1.4.803:=2)))

      Reply
  • Hi Salaudeen Rajack,

    Great sharepoint Blog, Nice Article,thanks for sharing.Looking forward for more posts like this.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *