Emergency server help: get in touch

Get-ADUser PowerShell Examples: 25 Queries for Active Directory

Twenty-five tested Get-ADUser queries for Windows Server 2016 to 2025: identity, filters, LDAP filters, OU scope, disabled, locked and expired accounts, last logon, password expiry, group membership, CSV reports and performance tips.

Published Updated 11 min read

These Get-ADUser PowerShell examples cover the queries Active Directory administrators run every week: finding one user, filtering thousands, reading extra attributes, checking logon and password dates, listing group membership and exporting clean reports. Every command works with the ActiveDirectory module on Windows Server 2016 to 2025 and on Windows 11 with RSAT.

Short answer: Use Get-ADUser -Identity jsmith -Properties * to inspect one account, and Get-ADUser -Filter "Enabled -eq 'True'" -SearchBase "OU=Staff,DC=contoso,DC=com" -Properties Department to query many. Filter on the server with -Filter or -LDAPFilter, request only the properties you need, and pipe to Export-Csv for reports.

Which query style to use

ParameterUse it forProsCons
-IdentityOne known account (sAMAccountName, DN, GUID or SID)Fastest; exact matchThrows an error if the user does not exist
-FilterMost searchesPowerShell-style operators; friendly property names such as EnabledOnly * wildcards; some quoting rules
-LDAPFilterBitwise flags, recursive membership, filters copied from other toolsFull LDAP syntax, matching rulesUses raw attribute names only
Search-ADAccountDisabled, locked, expired, inactive accountsReady-made switchesFewer filter options

Prerequisites

  • The ActiveDirectory module. On Windows Server: Install-WindowsFeature RSAT-AD-PowerShell. On Windows 11: Add-WindowsCapability -Online -Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0.
  • A reachable domain controller running Active Directory Web Services (TCP 9389). The cmdlets talk to ADWS, not directly to LDAP.
  • A normal domain account can read most user attributes. Some attributes, such as BitLocker or LAPS data, need delegated rights.

Basic lookups (examples 1–5)

The first Get-ADUser PowerShell examples retrieve single accounts and show which properties you get by default.

# 1. One user by sAMAccountName, DN, SID or GUID
Get-ADUser -Identity jsmith
Get-ADUser -Identity "CN=John Smith,OU=Staff,DC=contoso,DC=com"
# 2. One user with extra properties
Get-ADUser -Identity jsmith -Properties Department, Title, Manager, EmailAddress
# 3. Every attribute that has a value (use for discovery, not in scripts)
Get-ADUser -Identity jsmith -Properties *
# 4. Find a user by UPN or e-mail address
Get-ADUser -Filter "UserPrincipalName -eq 'john.smith@contoso.com'"
Get-ADUser -Filter "mail -eq 'john.smith@contoso.com'" -Properties mail
# 5. Name search with a wildcard
Get-ADUser -Filter "Name -like 'John*'" | Select-Object Name, SamAccountName, Enabled

Without -Properties, Get-ADUser returns a small default set: DistinguishedName, Enabled, GivenName, Name, ObjectClass, ObjectGUID, SamAccountName, SID, Surname and UserPrincipalName. Anything else, including mail, Department and LastLogonDate, must be requested.

Filter syntax (examples 6–10)

The -Filter parameter accepts -eq, -ne, -lt, -le, -gt, -ge, -like, -notlike, -and, -or and -not. Only the * wildcard is supported. Put the filter in double quotes and string values in single quotes so variables expand correctly.

# 6. Enabled users in one department
Get-ADUser -Filter "Enabled -eq 'True' -and Department -eq 'Finance'" -Properties Department
# 7. Use a variable inside the filter
$dept = 'Sales'
Get-ADUser -Filter "Department -eq '$dept'" -Properties Department, Title
# 8. Users whose password never expires
Get-ADUser -Filter "PasswordNeverExpires -eq 'True'" -Properties PasswordNeverExpires
# 9. Accounts created in the last 30 days (single quotes: the module reads $since)
$since = (Get-Date).AddDays(-30)
Get-ADUser -Filter 'whenCreated -ge $since' -Properties whenCreated |
    Sort-Object whenCreated | Select-Object Name, whenCreated
# 10. Users with an empty attribute (no e-mail address)
Get-ADUser -Filter "Enabled -eq 'True' -and mail -notlike '*'" | Select-Object Name, SamAccountName

In example 10, -notlike '*' means “attribute not set”. The same query as an LDAP filter is (&(!(mail=*))(!(userAccountControl:1.2.840.113556.1.4.803:=2))). Date comparisons such as example 9 are safest with the filter in single quotes, so the module converts the DateTime variable itself instead of relying on your regional date format.

LDAP filters (examples 11–12)

# 11. Enabled users only, using the ACCOUNTDISABLE bit (2) of userAccountControl
Get-ADUser -LDAPFilter '(!userAccountControl:1.2.840.113556.1.4.803:=2)'
# 12. Users with a service principal name (often service accounts)
Get-ADUser -LDAPFilter '(servicePrincipalName=*)' -Properties servicePrincipalName |
    Select-Object SamAccountName, servicePrincipalName

The OID 1.2.840.113556.1.4.803 is the bitwise AND matching rule; 1.2.840.113556.1.4.804 is bitwise OR.

Search base and scope (examples 13–14)

# 13. All users in an OU and its child OUs (Subtree is the default)
Get-ADUser -Filter * -SearchBase "OU=Staff,DC=contoso,DC=com"
# 14. Only the OU itself, not child OUs, against a specific DC
Get-ADUser -Filter * -SearchBase "OU=Staff,DC=contoso,DC=com" -SearchScope OneLevel -Server dc01.contoso.com

-SearchScope accepts Base, OneLevel and Subtree. Use -Server when you have just changed an object and want to read it from the DC you wrote it to, before replication completes.

Disabled, locked and expired accounts (examples 15–17)

These Get-ADUser PowerShell examples mix Get-ADUser with Search-ADAccount, which has ready-made switches for account states.

# 15. Disabled users
Get-ADUser -Filter "Enabled -eq 'False'" | Select-Object Name, SamAccountName
Search-ADAccount -AccountDisabled -UsersOnly
# 16. Locked-out users, then unlock one
Search-ADAccount -LockedOut -UsersOnly | Select-Object Name, SamAccountName, LastLogonDate
Get-ADUser -Identity jsmith -Properties LockedOut, lockoutTime, BadLogonCount
Unlock-ADAccount -Identity jsmith
# 17. Expired accounts and accounts expiring in the next 14 days
Search-ADAccount -AccountExpired -UsersOnly
Search-ADAccount -AccountExpiring -UsersOnly -TimeSpan 14.00:00:00 |
    Select-Object Name, AccountExpirationDate

LockedOut is calculated from lockoutTime and the lockout duration of the policy that applies to the user. If a user is locked out again straight after an unlock, a device is still sending an old password; to trace where the bad passwords come from, see our guide on event 4740.

Last logon: lastLogonTimestamp vs LastLogonDate vs lastLogon (examples 18–19)

PropertySourceReplicatedAccuracy
lastLogonRaw attribute on each DCNoExact on that DC only
lastLogonTimestampRaw attributeYesUpdated only when older than msDS-LogonTimeSyncInterval (14 days by default, minus a random offset)
LastLogonDateModule property converted from lastLogonTimestampYesSame as above, as a readable date
# 18. Users with no logon in 90 days (good enough for cleanup, not for audits)
$cutoff = (Get-Date).AddDays(-90)
Get-ADUser -Filter 'Enabled -eq $true -and LastLogonDate -lt $cutoff' -Properties LastLogonDate |
    Select-Object Name, SamAccountName, LastLogonDate
# 19. Exact last logon for one user: query lastLogon on every DC
$user = 'jsmith'
$times = foreach ($dc in (Get-ADDomainController -Filter *).HostName) {
    $u = Get-ADUser -Identity $user -Properties lastLogon -Server $dc
    [pscustomobject]@{ DC = $dc; LastLogon = [datetime]::FromFileTime($u.lastLogon) }
}
$times | Sort-Object LastLogon -Descending | Select-Object -First 1

A lastLogon of 0 converts to 1 January 1601, which means “never on this DC”. Users who never signed in at all have no LastLogonDate, so example 18 does not return them. To include them, use -Filter 'Enabled -eq $true -and (LastLogonDate -lt $cutoff -or LastLogonDate -notlike "*")' and check whenCreated so brand-new accounts are not flagged.

Password dates and expiry (examples 20–21)

# 20. Password last set, expired flag and computed expiry date
Get-ADUser -Filter "Enabled -eq 'True' -and PasswordNeverExpires -eq 'False'" -SearchBase "OU=Staff,DC=contoso,DC=com" -Properties PasswordLastSet, PasswordExpired, 'msDS-UserPasswordExpiryTimeComputed' |
    Select-Object Name, PasswordLastSet, PasswordExpired,
        @{ n = 'PasswordExpires'; e = {
            $v = $_.'msDS-UserPasswordExpiryTimeComputed'
            if ($v -gt 0 -and $v -lt 9223372036854775807) { [datetime]::FromFileTime($v) } } }
# 21. Which password policy applies (domain policy or a fine-grained PSO)
Get-ADUserResultantPasswordPolicy -Identity jsmith
Get-ADDefaultDomainPasswordPolicy

msDS-UserPasswordExpiryTimeComputed is a constructed attribute: the DC calculates it from pwdLastSet and the maximum password age of the effective policy, including fine-grained password policies. It returns 0 when the user must change the password at next logon and 0x7FFFFFFFFFFFFFFF when the password never expires or a smart card is required. Because it is constructed, you must name it in -Properties and cannot use it inside -Filter.

Group membership (examples 22–23)

Group queries are the Get-ADUser PowerShell examples most often asked for by auditors, and the ones most often done wrong, because direct and nested membership differ.

# 22. Direct group membership
Get-ADPrincipalGroupMembership -Identity jsmith | Select-Object Name, GroupScope
(Get-ADUser -Identity jsmith -Properties MemberOf).MemberOf
# 23. Recursive (nested) membership with the in-chain matching rule
$dn = (Get-ADUser -Identity jsmith).DistinguishedName
Get-ADGroup -LDAPFilter "(member:1.2.840.113556.1.4.1941:=$dn)" | Select-Object Name
# ...and the reverse: every user in a group, including nested groups
Get-ADGroupMember -Identity 'GRP-Finance' -Recursive | Where-Object objectClass -eq 'user'

MemberOf does not include the primary group (normally Domain Users), and Get-ADPrincipalGroupMembership needs a global catalog. The matching rule 1.2.840.113556.1.4.1941 (LDAP_MATCHING_RULE_IN_CHAIN) walks nested groups on the DC and is the quickest way to get recursive membership for one user.

Reports and exports (examples 24–25)

# 24. Export a user report to CSV (UTF-8, no type header)
Get-ADUser -Filter "Enabled -eq 'True'" -SearchBase "OU=Staff,DC=contoso,DC=com" -Properties Department, Title, EmailAddress, LastLogonDate, Manager |
    Select-Object Name, SamAccountName, UserPrincipalName, Department, Title, EmailAddress, LastLogonDate,
        @{ n = 'Manager'; e = { if ($_.Manager) { (Get-ADUser -Identity $_.Manager).Name } } } |
    Export-Csv -Path C:\Reports\staff.csv -NoTypeInformation -Encoding UTF8
# 25. Test a query on a small sample, then count results per OU
Get-ADUser -Filter * -ResultSetSize 10
Get-ADUser -Filter * | Group-Object { $_.DistinguishedName -replace '^CN=.+?(?<!\\),', '' } |
    Sort-Object Count -Descending | Select-Object Count, Name

Example 24 calls Get-ADUser once per manager. For large exports, cache managers in a hashtable first, or export the Manager DN and resolve it in Excel.

Other domains, credentials and output

The same Get-ADUser PowerShell examples work against another domain in the forest, or with a different account, by adding two parameters:

# Query a child domain with an admin account from that domain
$cred = Get-Credential CHILD\admin
Get-ADUser -Filter "Department -eq 'IT'" -Server child.contoso.com -Credential $cred
# Search every domain in the forest, one after another
foreach ($domain in (Get-ADForest).Domains) {
    Get-ADUser -Filter "Surname -eq 'Smith'" -Server $domain |
        Select-Object @{ n = 'Domain'; e = { $domain } }, Name, SamAccountName
}
# Readable table on screen, full list in a grid you can filter
Get-ADUser -Filter "Department -eq 'IT'" -Properties Title | Format-Table Name, Title -AutoSize
Get-ADUser -Filter "Department -eq 'IT'" -Properties Title | Out-GridView

Querying each domain directly returns every attribute, which a global catalog search would not. The account you run as needs read access in each domain; across a forest trust, pass -Credential. Use Format-Table only at the end of a pipeline: its output is formatting objects and cannot be exported to CSV.

Useful userAccountControl checks

Several account flags live in the userAccountControl bit mask. The module exposes the common ones as properties, and the LDAP filter works for all of them:

FlagBitModule propertyLDAP filter
Account disabled2Enabled(userAccountControl:1.2.840.113556.1.4.803:=2)
Password not required32PasswordNotRequired(userAccountControl:1.2.840.113556.1.4.803:=32)
Password never expires65536PasswordNeverExpires(userAccountControl:1.2.840.113556.1.4.803:=65536)
Smart card required262144SmartcardLogonRequired(userAccountControl:1.2.840.113556.1.4.803:=262144)
Trusted for delegation524288TrustedForDelegation(userAccountControl:1.2.840.113556.1.4.803:=524288)
Kerberos pre-authentication not required4194304DoesNotRequirePreAuth(userAccountControl:1.2.840.113556.1.4.803:=4194304)

The last three are worth a monthly security check: accounts with “password not required” or “pre-authentication not required” are common findings in audits, and unconstrained delegation on a user account is rarely intended.

Performance tips

These Get-ADUser PowerShell examples scale to large domains if you follow a few rules:

  • Filter on the server. Get-ADUser -Filter * | Where-Object Department -eq 'Sales' downloads every user. -Filter "Department -eq 'Sales'" returns only matches.
  • Request only what you need. -Properties * returns every populated attribute plus the module’s extended properties; in a script, list the attributes by name.
  • Narrow the scope with -SearchBase and -SearchScope OneLevel.
  • Use indexed attributes such as sAMAccountName, userPrincipalName and lastLogonTimestamp in filters; *text* (leading wildcard) searches are slower.
  • Use -ResultSetSize while developing a query, and keep the default -ResultPageSize of 256 unless a DC times out.
  • Pin a DC with -Server in long scripts so reads and writes hit the same server.

Verify results

Cross-check any report before acting on it: compare the count with (Get-ADUser -Filter * -SearchBase $ou).Count, open two or three accounts in Active Directory Users and Computers with Advanced Features enabled, and check the Attribute Editor tab for the raw values of lastLogonTimestamp, pwdLastSet and userAccountControl. The Get-ADUser PowerShell examples above return the same values as the Attribute Editor, only converted to dates and booleans.

Troubleshooting common errors

ErrorCauseFix
“The term ‘Get-ADUser’ is not recognized”RSAT AD PowerShell not installedInstall RSAT-AD-PowerShell or the RSAT capability, then Import-Module ActiveDirectory
“Cannot find an object with identity: ‘x’ under: ‘DC=…'”Wrong name, or the user is in another domainCheck spelling; add -Server otherdomain.contoso.com; use -Filter to search instead
“Unable to contact the server… Active Directory Web Services”ADWS stopped or TCP 9389 blockedStart the ADWS service on the DC; open 9389 in the firewall
Property is empty in the outputNot requested with -PropertiesAdd it to -Properties
Filter returns nothing with a variableVariable inside single quotes, or a property expression like $user.NameAssign to a plain variable first; use "Name -eq '$name'"
“Invalid enumeration context” on huge queriesPipeline too slow; the ADWS enumeration expiredStore results in a variable first, then process them

Keep these Get-ADUser PowerShell examples in a snippets file and adapt the OU paths and attribute lists; most daily reports are combinations of examples 6, 13, 18, 20 and 24.

Get-ADUser PowerShell examples at a glance

Get-ADUser PowerShell Examples summary card: Use Get-ADUser -Identity jsmith -Properties * to inspect one account, and Get-ADUser -Filter "Enabled -eq 'True'"…
In short: Use Get-ADUser -Identity jsmith -Properties * to inspect one account, and Get-ADUser -Filter “Enabled -eq ‘True'” -SearchBase “OU=Staff,DC=contoso,DC=com” -Properties Department to query many.

Official documentation: Get-ADUser (ActiveDirectory module), Search-ADAccount, ms-DS-User-Password-Expiry-Time-Computed attribute.

Related guides: Find inactive AD users and computers · AD Account Lockout Source: Easy Event 4740 Tracing · Bulk create AD users from CSV with PowerShell.

Frequently asked questions

What is the difference between LastLogonDate and lastLogon?

LastLogonDate is a converted copy of lastLogonTimestamp, which replicates but can be up to about 14 days behind. lastLogon is exact but stored separately on each domain controller, so you must query every DC and take the newest value.

How do I get all properties of an AD user with PowerShell?

Run Get-ADUser -Identity username -Properties *. Use it to discover attribute names, then list only the properties you need in scripts because -Properties * is slower.

Why can I not use msDS-UserPasswordExpiryTimeComputed in -Filter?

It is a constructed attribute that the domain controller calculates when you read it, so it cannot be searched. Request it with -Properties and filter the results with Where-Object.

How do I list nested group membership for a user?

Use Get-ADGroup with the LDAP filter member:1.2.840.113556.1.4.1941:= followed by the user’s distinguished name. The in-chain matching rule returns direct and nested groups in one query.

Free website test

Is your website set up right?

Check SSL, security headers, redirects, robots.txt, sitemap, llms.txt and security.txt in one test. It takes about 30 seconds.