Monday, July 8, 2013

Find and Delete Orphaned Users in SharePoint with PowerShell

Some time 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

Now, with PowerShell, We can Find and Delete orphaned users in SharePoint. Here is the script: I've made it work with SharePoint 2007 also.

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")

#Functions to Imitate SharePoint 2010 Cmdlets in MOSS 2007
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
}

#Function to Check if an User exists in AD
function CheckUserExistsInAD()
   {
   Param( [Parameter(Mandatory=$true)] [string]$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   
 }
 
 $WebAppURL="https://sharepoint.crescent.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!"
                                    
                                    #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.



You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Check out these SharePoint products:

31 comments :

  1. Hi Salaudeen Rajack,

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








    Sharepoint Developers


    ReplyDelete
  2. How to change script to remove disabled accounts from AD ? :) Thanks!

    ReplyDelete
    Replies
    1. Just change the Filter parameter in the function CheckUserExistsInAD() to:
      (&(objectCategory=person)(objectClass=user)( !(userAccountControl:1.2.840.113556.1.4.803:=2)))

      Delete
  3. 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(ad\9781) from http://stg2-community.com doesn't Exists in AD! and Zevis, Sophi(ad\158) from http://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?

    ReplyDelete
  4. Ya know. Forget I said anything - it works! Just let it sit for a while. Thanks for the awesome script.

    ReplyDelete
  5. can we write the output in a csv file? if yes then please share

    ReplyDelete
    Replies
    1. Simple! Just use: $User.LoginName | out-file "d:\OrphanedUsersRpt.txt" -append after line# 78.

      Delete
    2. Great..it worked..You Are The MAN :)

      Delete
    3. 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.

      Delete
  6. 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.

    ReplyDelete
  7. 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 Domian1\user1 move to Domain2\User1. Domain1\user1 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 ??

    ReplyDelete
  8. 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.

    ReplyDelete
  9. 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:\Powershell\FindOrphanedUsers.ps1:114 char:13
    + $WebsColl = <<<< $site.AllWebs | Where {$_.HasUniqueRoleAssignments -eq $Tr
    ue} | ForEach-Object {
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : OperatorFailed

    ReplyDelete
  10. This script was a great starting point. Thanks for sharing.

    ReplyDelete
  11. 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

    ReplyDelete
    Replies
    1. 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.

      Delete
  12. 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

    ReplyDelete
  13. 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.

    ReplyDelete
    Replies
    1. To find all disabled users, use:
      Get-ADUser -Filter {Enabled -eq $false} | FT samAccountName

      Delete
    2. 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.

      Delete
    3. 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.

      Delete
    4. 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

      Delete
  14. 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 !

    ReplyDelete
    Replies
    1. 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

      Delete
  15. Anyone else getting an unexpected token or expression error on line 49?

    ReplyDelete
  16. I run this but get the error CheckUserExistsInAD : Cannot bind argument to parameter 'UserLoginID' because it is an empty string. Any idea why?

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

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

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

    ReplyDelete
    Replies
    1. All documents and List items stays intact - except the created by or modified fields replaced with "System Account"

      Delete
  20. 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.

    ReplyDelete

Please Login and comment to get your questions answered!

You might also like:

Related Posts Plugin for WordPress, Blogger...