Discovering Stale User Accounts with PowerShell

By: Justin Braun
Posted on: March 30, 2009

Back in December I wrote a posting on “Discovering Stale Computer Accounts with PowerShell”.  Today I received an email from one of my readers (Thanks Matt for writing!) trying to adjust the script to query for stale user accounts.  The script that I created in the previous entry is a good starting point, but requires some modifications to work properly for user accounts.

The biggest change in the script is that the DirectorySearcher filter has to be modified to look for user accounts.  Simply changing  the filter to “user” from “computer” doesn’t quite work as for some reason ADSI will retrieve both the user accounts as well as the computer accounts.  We can further limit the search by adding the ObjectCategory in addition to the ObjectClass.

This particular example will query on the last password change date.

function Get-StaleUserAccounts
{   
    # Use Directory Services object to attach to the domain
    $searcher = new-object DirectoryServices.DirectorySearcher([ADSI]"")
    
    # Filter down to user accounts
    #when you query for objectClass=User, you will not only get user accounts but also computer accounts. 
    #To limit the search to true user accounts, you would have to also include the objectCategory
    $searcher.filter = "(&(objectCategory=person)(objectClass=User))"
    
    # Cache the results
    $searcher.CacheResults = $true
    $searcher.SearchScope = “Subtree”
    $searcher.PageSize = 1000
    
    # Find anything you can that matches the definition of being a user object
    $accounts = $searcher.FindAll()
    
    # Check to make sure we found some accounts
    if($accounts.Count -gt 0)
    {             
        foreach($account in $accounts)
        {
            $LastPassChange = [datetime]::FromFileTimeUTC($account.Properties["pwdlastset"][0]);    
        
            # Determine the timespan between the two dates
            $datediff = new-TimeSpan $LastPassChange $(Get-Date);
            
            # Create an output object for table formatting
            $obj = new-Object PSObject;
            
            # Add member properties with their name and value pair
            $obj | Add-Member NoteProperty AccountName($account.Properties["name"][0]);
            $obj | Add-Member NoteProperty LastPasswordChange($LastPassChange);
            $obj | Add-Member NoteProperty DaysSinceChange($datediff.Days);
            
            # Write the output to the screen
            Write-Output $obj;
        }
    }
}
 
# Get user accounts where a password change hasn't occurred in 60 days or more
# If nothing outputted, then there are no accounts that meet that criteria
Get-StaleUserAccounts |Where-Object {$_.DaysSinceChange -gt 60}

Related Articles

The Project Location is Not Trusted

This dialog box appears if you attempt to open or create a client project on a Universal Naming Convention (UNC) path.
2018 12 19 17 24 28

My first look at Windows Sandbox

Earlier this week, Windows Insiders who were part of the Fast Ring, got their first glimpse of an isolated desktop environment called Windows Sandbox.

PowerShell with Compellent and Exchange 2010

I’ve been doing lots of work in the lab lately with Exchange 2010 to understand all the new change