Cheat sheet

Active Directory PowerShell cheat sheet

ActiveDirectory module cmdlets on one sheet: users, groups, computers and OUs, password resets and unlocks, finding locked, disabled and stale accounts, and -Filter versus -LDAPFilter.

All cheat sheets

Everyday ActiveDirectory module cmdlets for help desk and sysadmin work, with realistic examples for the contoso.com domain. Change names and OUs to match yours.

Getting started

Task Command
Install on Windows 10 or 11 (admin) Add-WindowsCapability -Online -Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0
Install on Windows Server Install-WindowsFeature RSAT-AD-PowerShell
Load the module Import-Module ActiveDirectory
List every AD cmdlet Get-Command -Module ActiveDirectory
Domain summary and FSMO roles Get-ADDomain | Select-Object DNSRoot, PDCEmulator, RIDMaster, InfrastructureMaster
Domain controllers Get-ADDomainController -Filter * | Select-Object Name, Site, IPv4Address, IsGlobalCatalog
Find the PDC emulator Get-ADDomainController -Discover -Service PrimaryDC

The module talks to Active Directory Web Services on the domain controllers (TCP 9389). Add -Server dc01.contoso.com to target one DC.

Users

Task Command
One user (by sAMAccountName, DN, GUID or SID) Get-ADUser -Identity jdoe
Extra properties Get-ADUser jdoe -Properties Title, Department, LastLogonDate, PasswordLastSet
Every property (slow, use for one user) Get-ADUser jdoe -Properties *
Search by name Get-ADUser -Filter "Name -like 'John*'"
All users in one OU Get-ADUser -Filter * -SearchBase "OU=Staff,DC=contoso,DC=com"
Users with no email address Get-ADUser -Filter 'EmailAddress -notlike "*"'
Headcount by department Get-ADUser -Filter * -Properties Department | Group-Object Department | Sort-Object Count -Descending
Update attributes Set-ADUser jdoe -Title 'Help Desk Analyst' -Department IT -Office 'Building 2'
Set an attribute with no named parameter Set-ADUser jdoe -Replace @{extensionAttribute1 = 'Contractor'}
Disable, enable Disable-ADAccount jdoe, Enable-ADAccount jdoe
Account expiry (expires at 00:00 on that date), or remove it Set-ADAccountExpiration jdoe -DateTime '2026-12-31', or Clear-ADAccountExpiration jdoe
Move to another OU Get-ADUser jdoe | Move-ADObject -TargetPath "OU=Leavers,DC=contoso,DC=com"
Delete (asks to confirm) Remove-ADUser jdoe

New user

New-ADUser -Name 'Jane Doe' -GivenName Jane -Surname Doe `
    -SamAccountName jdoe -UserPrincipalName jdoe@contoso.com `
    -Path 'OU=Staff,DC=contoso,DC=com' `
    -AccountPassword (Read-Host -AsSecureString 'Initial password') `
    -ChangePasswordAtLogon $true -Enabled $true

Without -AccountPassword and -Enabled $true, the new account is created disabled.

Passwords and lockouts

Task Command
Reset a password Set-ADAccountPassword jdoe -Reset -NewPassword (Read-Host -AsSecureString 'New password')
Force a change at next sign-in Set-ADUser jdoe -ChangePasswordAtLogon $true
Unlock an account Unlock-ADAccount jdoe
Is it locked, and when was the last bad password? Get-ADUser jdoe -Properties LockedOut, AccountLockoutTime, LastBadPasswordAttempt, BadLogonCount
All locked-out users Search-ADAccount -LockedOut -UsersOnly | Select-Object Name, SamAccountName
When was the password last set? Get-ADUser jdoe -Properties PasswordLastSet, PasswordNeverExpires
Domain password and lockout policy Get-ADDefaultDomainPasswordPolicy
Fine-grained policy that applies to a user Get-ADUserResultantPasswordPolicy jdoe (no output means the domain policy applies)

BadLogonCount and LastBadPasswordAttempt are not replicated, so each DC can show different values. Failed passwords are forwarded to the PDC emulator, so it is a good DC to ask with -Server.

Finding disabled, stale and expiring accounts

Find Command
Disabled users Search-ADAccount -AccountDisabled -UsersOnly or Get-ADUser -Filter 'Enabled -eq $false'
No sign-in for 90 days Search-ADAccount -AccountInactive -TimeSpan 90.00:00:00 -UsersOnly
Enabled users idle 90 days, with dates $cutoff = (Get-Date).AddDays(-90), then Get-ADUser -Filter 'Enabled -eq $true -and LastLogonDate -lt $cutoff' -Properties LastLogonDate
Stale computers Search-ADAccount -AccountInactive -TimeSpan 90.00:00:00 -ComputersOnly
Expired accounts Search-ADAccount -AccountExpired -UsersOnly
Accounts expiring in the next 14 days Search-ADAccount -AccountExpiring -TimeSpan 14.00:00:00 -UsersOnly
Expired passwords Search-ADAccount -PasswordExpired -UsersOnly
Passwords set never to expire Search-ADAccount -PasswordNeverExpires -UsersOnly
Limit any search to one OU add -SearchBase "OU=Staff,DC=contoso,DC=com"

LastLogonDate comes from lastLogonTimestamp, which replicates but can lag by up to about 14 days. Accounts that never signed in have no value and do not match a date filter.

Groups and membership

Task Command
One group Get-ADGroup 'SG-Finance-Read' -Properties Description, ManagedBy
New security group New-ADGroup -Name 'SG-Finance-Read' -GroupScope Global -GroupCategory Security -Path 'OU=Groups,DC=contoso,DC=com' -Description 'Read access to the Finance share'
Add members Add-ADGroupMember -Identity 'SG-Finance-Read' -Members jdoe, asmith
Remove a member (asks to confirm) Remove-ADGroupMember -Identity 'SG-Finance-Read' -Members jdoe
Direct members Get-ADGroupMember 'SG-Finance-Read' | Select-Object Name, ObjectClass
Members including nested groups Get-ADGroupMember 'Domain Admins' -Recursive | Select-Object Name
Groups a user belongs to Get-ADPrincipalGroupMembership jdoe | Select-Object Name
Direct groups as DNs (Get-ADUser jdoe -Properties MemberOf).MemberOf
Groups with no members Get-ADGroup -Filter * -Properties Members | Where-Object { -not $_.Members }

Group scopes: DomainLocal, Global, Universal. Categories: Security, Distribution. MemberOf does not list the primary group (usually Domain Users).

Computers

Task Command
One computer with useful details Get-ADComputer PC01 -Properties OperatingSystem, LastLogonDate, IPv4Address
Computers by name pattern in an OU Get-ADComputer -Filter "Name -like 'LIB-*'" -SearchBase 'OU=Workstations,DC=contoso,DC=com'
All servers Get-ADComputer -Filter 'OperatingSystem -like "*Server*"' -Properties OperatingSystem | Select-Object Name, OperatingSystem
Count by operating system Get-ADComputer -Filter * -Properties OperatingSystem | Group-Object OperatingSystem | Sort-Object Count -Descending
Disable a computer account Get-ADComputer PC01 | Disable-ADAccount
Delete a computer (asks to confirm) Remove-ADComputer PC01

If Remove-ADComputer fails because the object has child objects (for example BitLocker recovery keys), use Get-ADComputer PC01 | Remove-ADObject -Recursive.

Organizational units

Task Command
List OUs Get-ADOrganizationalUnit -Filter * | Select-Object Name, DistinguishedName
New OU (protected from deletion by default) New-ADOrganizationalUnit -Name Laptops -Path 'OU=Workstations,DC=contoso,DC=com'
Remove protection Set-ADOrganizationalUnit 'OU=Old,DC=contoso,DC=com' -ProtectedFromAccidentalDeletion $false
Delete an OU and everything in it Remove-ADOrganizationalUnit 'OU=Old,DC=contoso,DC=com' -Recursive
Move any object Move-ADObject 'CN=PC01,OU=Workstations,DC=contoso,DC=com' -TargetPath 'OU=Laptops,OU=Workstations,DC=contoso,DC=com'

-Filter or -LDAPFilter?

-Filter -LDAPFilter
Syntax PowerShell style Raw LDAP
Operators -eq -ne -like -notlike -lt -le -gt -ge -and -or -not = >= <= & | ! and * wildcards
Property names Module names such as Enabled, LastLogonDate, or LDAP names LDAP names only, such as sAMAccountName, sn
Everything -Filter * -LDAPFilter '(objectClass=*)'
Name starts with Smi -Filter "Surname -like 'Smi*'" -LDAPFilter '(sn=Smi*)'
IT or HR department -Filter "Department -eq 'IT' -or Department -eq 'HR'" -LDAPFilter '(|(department=IT)(department=HR))'
Disabled accounts -Filter 'Enabled -eq $false' -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=2)'
No email set -Filter 'EmailAddress -notlike "*"' -LDAPFilter '(!(mail=*))'
Parameter What it does
-SearchBase 'OU=Staff,DC=contoso,DC=com' Start the search at this OU instead of the domain root
-SearchScope Base | OneLevel | Subtree This object only, direct children only, or everything below (default)
-Properties Name1, Name2 Return extra attributes. * returns all of them.
-ResultSetSize 100 Stop after 100 results
-Server dc01.contoso.com Ask a specific domain controller

Tips: filter on the server with -Filter rather than Where-Object on large directories. Add -WhatIf to any Set-, Add-, Move- or Remove- command to preview it first.