Active Directory · Windows PowerShell 5.1
Enabled AD user accounts with no recent logon
Which enabled user accounts in Active Directory have not logged on in the last 90 days (or the number of days you pass)?
Script
#Requires -Modules ActiveDirectory
# Enabled user accounts whose LastLogonDate is older than -Days (or empty). Read-only.
param(
[int]$Days = 90
)
$cutoff = (Get-Date).AddDays(-$Days)
Get-ADUser -Filter 'Enabled -eq $true' -Properties LastLogonDate, PasswordLastSet, Created, Description |
Where-Object { $_.Created -lt $cutoff } |
Where-Object { $null -eq $_.LastLogonDate -or $_.LastLogonDate -lt $cutoff } |
Sort-Object LastLogonDate |
Select-Object Name, SamAccountName, LastLogonDate, PasswordLastSet, Created, Description, DistinguishedName
Checked automatically against Microsoft's published cmdlet reference. KBY hasn't run it in your tenant; run it in a test environment first.
Where to run it
A domain-joined machine with the Active Directory module (RSAT) installed.
Reading the output
- LastLogonDate is derived from lastLogonTimestamp, which is replicated between domain controllers but isn't updated on every logon, so treat it as approximate.
- Accounts created inside the window are left out, because they haven't had -Days to log on. Accounts that have never logged on are included with an empty LastLogonDate.
- Accounts used only for Microsoft Entra ID or cloud sign-ins may show old on-premises logons and still be in use. Check the Entra ID sign-in activity before disabling any synced account.
Sources
The Microsoft reference page for every cmdlet the script calls, plus the API and product pages behind each permission and caveat.
Get-ADUser (ActiveDirectory)about_ActiveDirectory_ObjectModel (LastLogonDate, PasswordLastSet and the account flag properties)about_ActiveDirectory_Filter (Filter and LDAPFilter, bitwise AND matching rule)Get-Date (Microsoft.PowerShell.Utility)Where-Object (Microsoft.PowerShell.Core)Sort-Object (Microsoft.PowerShell.Utility)Select-Object (Microsoft.PowerShell.Utility)