PowerShell Script to Find Inactive AD Accounts Quickly
Search-ADAccount -AccountInactive -UsersOnly to find inactive AD user accounts; for example, Search-ADAccount -AccountInactive -UsersOnly | Select-Object Name, LastLogonDate lists inactive users with their last logon dates.Examples
How to Think About It
Search-ADAccount cmdlet with the -AccountInactive flag helps filter these accounts. You can then select properties like Name and LastLogonDate to see details.Algorithm
Code
Import-Module ActiveDirectory
$inactiveUsers = Search-ADAccount -AccountInactive -UsersOnly | Select-Object Name, LastLogonDate
foreach ($user in $inactiveUsers) {
Write-Output "$($user.Name) last logged on at $($user.LastLogonDate)"
}Dry Run
Let's trace finding inactive users through the code
Run Search-ADAccount
Returns users JohnDoe and JaneSmith flagged as inactive with their last logon dates.
Select Name and LastLogonDate
Filters output to only show Name and LastLogonDate properties.
Print each user's info
Outputs 'JohnDoe last logged on at 1/15/2023 10:00:00 AM' and 'JaneSmith last logged on at 12/20/2022 9:30:00 AM'.
| Name | LastLogonDate |
|---|---|
| JohnDoe | 1/15/2023 10:00:00 AM |
| JaneSmith | 12/20/2022 9:30:00 AM |
Why This Works
Step 1: Search-ADAccount finds inactive users
The Search-ADAccount -AccountInactive -UsersOnly command queries Active Directory for user accounts that have not logged in recently.
Step 2: Selecting properties for clarity
Using Select-Object Name, LastLogonDate extracts only the user name and last logon date to keep output simple and readable.
Step 3: Output formatting
Looping through results and printing each user's name and last logon date makes the output easy to understand.
Alternative Approaches
Import-Module ActiveDirectory $daysInactive = 90 $cutoffDate = (Get-Date).AddDays(-$daysInactive) $inactiveUsers = Search-ADAccount -UsersOnly | Where-Object { $_.LastLogonDate -lt $cutoffDate } | Select Name, LastLogonDate $inactiveUsers | ForEach-Object { Write-Output "$($_.Name) last logged on at $($_.LastLogonDate)" }
Import-Module ActiveDirectory
$inactiveUsers = Get-ADUser -Filter {LastLogonTimeStamp -lt $([DateTime]::Now.AddDays(-90))} -Properties LastLogonTimeStamp | Select Name, @{Name='LastLogonDate';Expression={[DateTime]::FromFileTime($_.LastLogonTimeStamp)}}
$inactiveUsers | ForEach-Object { Write-Output "$($_.Name) last logged on at $($_.LastLogonDate)" }Complexity: O(n) time, O(n) space
Time Complexity
The script queries all user accounts once, so time grows linearly with the number of users (n).
Space Complexity
Stores all inactive user objects in memory, so space also grows linearly with the number of inactive accounts.
Which Approach is Fastest?
Using Search-ADAccount with built-in filters is faster and simpler than manual filtering with Get-ADUser.
| Approach | Time | Space | Best For |
|---|---|---|---|
| Search-ADAccount -AccountInactive | O(n) | O(n) | Quickly find inactive users with minimal code |
| Custom filter with Search-ADAccount and Where-Object | O(n) | O(n) | Flexible inactivity period but more processing |
| Get-ADUser with LDAP filter | O(n) | O(n) | Precise filtering with timestamp conversion |