Finding Expired and Unused AD Accounts

I am using the following command to find any expired account or accounts that have not logged in within 45 days. Do you have any suggestions for improving the script? Is there anything I am missing when checking for expired or unused accounts?

get-aduser -filter * -SearchBase $varOUPath -Properties PasswordExpired,Enabled,LastLogonDate,Created,lastLogonTimestamp,

AccountExpirationDate |

Where-Object {($.PasswordExpired -eq $True) -or ($.Enabled -eq $False) -or
(($.LastLogonDate -lt $varInactiveDate) -and ($.LastLogonDate -ne $NULL)) -or (($.created -lt $varInactiveDate) -and ($.LastLogonDate -eq $NULL)) -or (($.AccountExpirationDate -le (get-date)) -and ($.AccountExpirationDate -ne $null))}|

Select-Object Name,SamAccountname,PasswordExpired,Enabled,Created,Lastlogondate,@{n=‘LogonTimeStamp(Replicated)’; e={[datetime]::FromFileTime($_.LastlogonTimestamp).ToString(‘g’)}},AccountExpirationDate

So that is going to take a lot longer to run. Check out the filter parameter as your using an * to basically say All vs filtering just on what you want.


$Date = Get-Date

$45DaysAgo = $Date.AddDays(-45)

#Grab Users who haven’t logged into the system in over 45 days.

Get-ADUser -Filter {LastLogonDate -lt $45DaysAgo} -Properties LastLogonDate | Select-Object -Property SamAccountName,Lastlogondate

Find Expired acccounts/disable ones.

Search-ADAccount -AccountExpired

Search-ADAccount -AccountDisabled


get-aduser -filter {LastLogonDate -LT $90Daysgo} -SearchBase $varOUPath -Properties PasswordExpired,Enabled,LastLogonDate,Created,lastLogonTimestamp,

To be clear, you should do all of your filtering (if possible) here:

Get-ADUser -Filter {(LastLogonDate -lt $45DaysAgo) -and (PasswordExpired -eq $True) -and (Enabled -eq $False)}

Thanks for the updates! I will try and add the expression in the filter section of get-aduser.

I am wondering if there is a limitation to how many expressions you can put in the filter? After adding 3 expressions I get a parsing error. I did run the command with everything in the where statement and 3 expressions moved to the filter. (Gained about 12 milliseconds, see below)


get-aduser : Error parsing query: ‘(PasswordExpired -eq $True) -or (Enabled -eq $False) -or ((LastLogonDate -lt $varInactiveDate) -and (LastLogonDate -like “")) -or ((AccountExpirationDate -le (get-date)) -and (AccountExpirationDate -like "”))’ Error
Message: ‘syntax error’ at position: ‘160’.
At line:1 char:1

  • get-aduser -SearchBase $varOUPath -Properties PasswordExpired,Enabled …
  • CategoryInfo : ParserError: (:slight_smile: [Get-ADUser], ADFilterParsingException
  • FullyQualifiedErrorId : Error parsing query: ‘(PasswordExpired -eq $True) -or (Enabled -eq $False) -or ((LastLogonDate -lt $varInactiveDate) -and (LastLogonDate -like “")) -or ((AccountExpirationDate -le (get-date)) -and (AccountExpirationDate -like
    ”))’ Error Message: ‘syntax error’ at position: ‘160’.,Microsoft.ActiveDirectory.Management.Commands.GetADUser

<# with where statements only 24855 User Objects
Days : 0
Hours : 0
Minutes : 0
Seconds : 17
Milliseconds : 950
Ticks : 179504590

<# added 3 expressions to the filter 24855 User Objects
Days : 0
Hours : 0
Minutes : 0
Seconds : 5
Milliseconds : 666
Ticks : 56664759

What exactly are you looking for? If you are doing a comparison on a date, then there should be no need to see if is not null (e.g. -like ‘*’). The biggest issue is you are looking for people that are already disabled. You can try a filter something like this:

(Enabled -eq $True) -and #Account still enabled
(PasswordExpired -eq $True) -or  #Account password expired
(LastLogonDate -lt (Get-Date).AddDays(-45)) -or #Account Last Logon is beyond 45 days
(AccountExpirationDate -gt (get-date)) #Account has expired

Rather than trying to jam all of stuff you want into the filter, I would start with the first 2 and try it. Then add the third and try it. Another option is Search-ADAccount:

Search-ADAccount -AccountDisabled
Search-ADAccount -AccountExpired
Search-ADAccount -AccountExpiring
Search-ADAccount -AccountInactive

I still need to do some more testing but seems to have an error after a 4th entry is added.

The following works but if I add another entry it displays the error listed. I might be doing something wrong but was wondering what the limitations are when using the filter if any?

(PasswordExpired -eq $True) -or (Enabled -eq $False) -or ((LastLogonDate -lt $varInactiveDate) -and (LastLogonDate -like “*”))