Everyday Active Directory PowerShell commands (read-only)
Copy-and-paste PowerShell commands for the Active Directory questions that come up every week, from locked-out users to stale accounts and domain controller health. Nothing here changes anything.
Most Active Directory questions don’t need a fancy tool. Who’s locked out? Which accounts haven’t been used in months? Who’s actually in Domain Admins? A one-line PowerShell command answers each of these in seconds.
Every command on this page is read-only. They look things up and report back; none of them change, disable, unlock, or delete anything. That makes them safe to run while you learn what’s in your directory.
Before you start
You need the ActiveDirectory PowerShell module:
- On a domain controller, it’s already installed.
- On a Windows 10 or 11 admin workstation, install RSAT: Active Directory Domain Services and Lightweight Directory Services Tools from Settings > System > Optional features.
Open PowerShell as a user with rights to read the directory (a normal domain account can read most of it), then load the module:
Import-Module ActiveDirectory
Tip: to save any result to a spreadsheet, add | Export-Csv to the end of the command, like this:
Search-ADAccount -LockedOut -UsersOnly | Export-Csv -Path C:\Temp\locked-out.csv -NoTypeInformation
User accounts
Who’s locked out right now? Lists every user account that’s currently locked out, the first thing to check when someone calls saying they can’t log in.
Search-ADAccount -LockedOut -UsersOnly | Select-Object Name, SamAccountName, LastLogonDate
Which user accounts are disabled? Good for confirming offboarded employees were actually shut off. (The free onboarding and offboarding checklist covers everything else to shut off.)
Search-ADAccount -AccountDisabled -UsersOnly | Select-Object Name, SamAccountName
Which users haven’t logged in for 90 days? Your starting list for stale-account cleanup and a favorite auditor question.
Search-ADAccount -AccountInactive -TimeSpan 90.00:00:00 -UsersOnly | Select-Object Name, SamAccountName, LastLogonDate
About that “last logon” date: to reduce replication traffic, Active Directory only updates the replicated last-logon value every so often, so by design it can be 9 to 14 days behind. It’s reliable for finding accounts unused for months, but don’t use windows shorter than about 14 days, and never disable an account based on one report without checking with its owner.
Whose passwords are set to never expire? Often service accounts and forgotten test accounts. Worth reviewing, since most auditors will ask why.
Search-ADAccount -PasswordNeverExpires -UsersOnly | Select-Object Name, SamAccountName
Whose passwords have already expired?
Search-ADAccount -PasswordExpired -UsersOnly | Select-Object Name, SamAccountName
When does each user’s password expire? Handy for warning people before they’re locked out on a Monday morning.
Get-ADUser -Filter 'Enabled -eq $true' -Properties 'msDS-UserPasswordExpiryTimeComputed' |
Select-Object Name, @{Name='PasswordExpires'; Expression={
$v = $_.'msDS-UserPasswordExpiryTimeComputed'
if ($v -eq 0) { 'Must change at next logon' }
elseif ($v -ge [long]::MaxValue) { 'Never' }
else { [datetime]::FromFileTime($v) }
}} | Sort-Object PasswordExpires
Active Directory stores special values for two cases, so the command translates them: accounts set to never expire show Never, and accounts flagged to change their password at next logon say so, instead of showing a meaningless date.
Everything about one user
Shows every attribute on one account. Replace jsmith with the user’s login name.
Get-ADUser -Identity jsmith -Properties *
Groups and admin access
Who’s in Domain Admins, including through nested groups?
The single most important list in your directory. The -Recursive switch includes people who get admin rights through a group inside the group.
Get-ADGroupMember -Identity 'Domain Admins' -Recursive | Select-Object Name, SamAccountName, objectClass
Run it again with 'Enterprise Admins' and 'Administrators' for the full picture.
Which groups is a user in?
Get-ADPrincipalGroupMembership -Identity jsmith | Select-Object Name
Computers
Which computers haven’t checked in for 90 days? Old PCs and servers that were retired but never removed from the domain.
Search-ADAccount -AccountInactive -TimeSpan 90.00:00:00 -ComputersOnly | Select-Object Name, LastLogonDate
What operating systems are on the domain? A quick inventory, useful for spotting machines on unsupported versions of Windows.
Get-ADComputer -Filter * -Properties OperatingSystem, OperatingSystemVersion |
Select-Object Name, OperatingSystem, OperatingSystemVersion | Sort-Object OperatingSystem
Domain controllers and domain health
List every domain controller
Get-ADDomainController -Filter * | Select-Object Name, IPv4Address, OperatingSystem, Site, IsGlobalCatalog
Which domain controller holds each FSMO role? You’ll need this before retiring or rebuilding a domain controller.
Get-ADDomain | Select-Object PDCEmulator, RIDMaster, InfrastructureMaster
Get-ADForest | Select-Object SchemaMaster, DomainNamingMaster
What’s the domain password policy? Minimum length, lockout threshold, and maximum password age, which auditors often ask for.
Get-ADDefaultDomainPasswordPolicy
Is replication healthy?
These are classic command-line tools, not PowerShell cmdlets, but they run fine in PowerShell. Run them on a domain controller. repadmin /replsummary shows replication failures between domain controllers at a glance, and dcdiag runs a broad health check.
repadmin /replsummary
dcdiag /q
The /q switch tells dcdiag to show only errors. No output is good news.
Going further
- Planning to replace old domain controllers? See Retiring old domain controllers before Server 2016 support ends.
- When you’re ready to act on these reports (disabling stale accounts, unlocking users), do it deliberately and one change at a time, and keep your CSV reports as a record of what you changed and why.
Sources
- Search-ADAccount (Microsoft Learn): the locked-out, disabled, inactive, and password search switches and the TimeSpan format
- lastLogonTimestamp is not accurate (Microsoft Learn): why the replicated last-logon value can be 9 to 14 days behind
- The LastLogonTimeStamp attribute: what it was designed for and how it works (Microsoft Ask the Directory Services Team): the update formula and intended use for finding inactive accounts
- ms-DS-Logon-Time-Sync-Interval attribute (Microsoft Learn): the setting that controls how often last-logon data replicates
- Get-ADUser, Get-ADGroupMember, Get-ADComputer, Get-ADDomainController, and Get-ADDefaultDomainPasswordPolicy (Microsoft Learn): syntax for the remaining commands
From Small Town Sysadmin
Get new guides by email
Plain-English tech tips, scam and security alerts, and fixes for small offices, whether you're the office manager or the IT pro. No spam, and you can unsubscribe anytime.