# Finding Expired and Unused AD Accounts

**URL:** <https://forums.powershell.org/t/finding-expired-and-unused-ad-accounts/11698>\
**Category:** PowerShell Help\
**Created:** [November 20, 2018, 1:57pm UTC](https://forums.powershell.org/t/finding-expired-and-unused-ad-accounts/11698 "2018-11-20T13:57:20Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![wbfick](https://avatars.discourse-cdn.com/v4/letter/w/ed655f/32.png) [@wbfick](https://forums.powershell.org/u/wbfick)\
**Post date:** [November 20, 2018, 1:57pm UTC](https://forums.powershell.org/t/finding-expired-and-unused-ad-accounts/11698/1 "2018-11-20T13:57:20Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![jefferyhayes](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/jefferyhayes/32/265_2.png) [@jefferyhayes](https://forums.powershell.org/u/jefferyhayes)\
**Post date:** [November 20, 2018, 2:30pm UTC](https://forums.powershell.org/t/finding-expired-and-unused-ad-accounts/11698/2 "2018-11-20T14:30:10Z")

</div>

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.

&nbsp;

$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

&nbsp;

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

---

<div class="post-metadata">

**Author:** ![rob-simmers](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/rob-simmers/32/1010_2.png) [@rob-simmers](https://forums.powershell.org/u/rob-simmers)\
**Post date:** [November 20, 2018, 2:46pm UTC](https://forums.powershell.org/t/finding-expired-and-unused-ad-accounts/11698/3 "2018-11-20T14:46:46Z")

</div>

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)}
```

---

<div class="post-metadata">

**Author:** ![wbfick](https://avatars.discourse-cdn.com/v4/letter/w/ed655f/32.png) [@wbfick](https://forums.powershell.org/u/wbfick)\
**Post date:** [November 20, 2018, 2:54pm UTC](https://forums.powershell.org/t/finding-expired-and-unused-ad-accounts/11698/4 "2018-11-20T14:54:56Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![wbfick](https://avatars.discourse-cdn.com/v4/letter/w/ed655f/32.png) [@wbfick](https://forums.powershell.org/u/wbfick)\
**Post date:** [November 21, 2018, 8:09am UTC](https://forums.powershell.org/t/finding-expired-and-unused-ad-accounts/11698/5 "2018-11-21T08:09:38Z")

</div>

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)

Error:

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 …
- 

```auto

```

- CategoryInfo : ParserError: (🙂 [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  
#\>

---

<div class="post-metadata">

**Author:** ![rob-simmers](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/rob-simmers/32/1010_2.png) [@rob-simmers](https://forums.powershell.org/u/rob-simmers)\
**Post date:** [November 21, 2018, 9:21am UTC](https://forums.powershell.org/t/finding-expired-and-unused-ad-accounts/11698/6 "2018-11-21T09:21:45Z")

</div>

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
```

---

<div class="post-metadata">

**Author:** ![wbfick](https://avatars.discourse-cdn.com/v4/letter/w/ed655f/32.png) [@wbfick](https://forums.powershell.org/u/wbfick)\
**Post date:** [November 21, 2018, 10:48am UTC](https://forums.powershell.org/t/finding-expired-and-unused-ad-accounts/11698/7 "2018-11-21T10:48:02Z")

</div>

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 “\*”))

&nbsp;

---

<div class="post-metadata">

**Author:** ![dotnVo](https://avatars.discourse-cdn.com/v4/letter/d/4af34b/32.png) [@dotnVo](https://forums.powershell.org/u/dotnVo)\
**Post date:** [May 16, 2024, 8:34pm UTC](https://forums.powershell.org/t/finding-expired-and-unused-ad-accounts/11698/8 "2024-05-16T20:34:08Z")

</div>


