Finding and managing disabled user accounts in Active Directory is a crucial administrative task for maintaining security and compliance. Disabled accounts can accumulate over time, creating security issues and cluttering your directory. The Get-ADUser disabled accounts cmdlet in PowerShell provides powerful capabilities to identify, filter, and export disabled user accounts efficiently. Whether you're conducting security audits, cleaning up inactive accounts, or using PowerShell to generate a list of disabled users for compliance reports, this guide covers methods to query disabled users across your entire domain or specific organizational units.
When you need to PowerShell export disabled users to CSV for reporting or auditing, the Get-ADUser cmdlet with the enabled false parameter provides flexible filtering options. This comprehensive guide shows you how to use the Get-ADUser filter disabled accounts and export them in multiple formats.
Method 1: Steps to get disabled users report using Get-ADUser cmdlet in PowerShell:
import-module activedirectory
$OutFile = 'C:\Scripts\DisabledUsers.csv'
# your output file
$filter = {Enabled -eq $false}
Get-ADUser -Filter $filter
| foreach {Add-Content -path
$OutFile "$($_.SamAccountName),
$($_.distinguishedName)"}
Method 2: Steps to get disabled users using Search-ADAccount cmdlet
To import Active Directory module:
Import-Module ActiveDirectory
To get all disabled user accounts:
Search-ADAccount -AccountDisabled -UsersOnly |
Select-Object Name, SamAccountName, DistinguishedName, LastLogonDate |
Export-CSV "C:\Scripts\DisabledUsers_SearchADAccount.csv" -NoTypeInformation
Finding disabled users in ADManager Plus::
Retrieve a complete list using Get-ADUser disabled filter across your entire Active Directory domain.
Get-ADUser -Filter {Enabled -eq $false} |
Select-Object Name, SamAccountName, DistinguishedName
Using Get-ADUser enabled false cmdlet with additional properties to retrieve disabled users along with their manager's email address for notification purposes.
$disabledUsers = Get-ADUser -Filter {Enabled -eq $false} -Properties Manager, EmailAddress, Department
$report = foreach ($user in $disabledUsers) {
$managerDN = $user.Manager
if ($managerDN) {
$manager = Get-ADUser $managerDN -Properties EmailAddress
[PSCustomObject]@{
UserName = $user.Name
UserEmail = $user.EmailAddress
Department = $user.Department
ManagerName = $manager.Name
ManagerEmail = $manager.EmailAddress
}
}
}
$report | Export-CSV "C:\Reports\DisabledUsers_WithManagers.csv" -NoTypeInformation
Identify accounts that were disabled within a specific timeframe for audit purposes.
$30DaysAgo = (Get-Date).AddDays(-30)
Get-ADUser -Filter {Enabled -eq $false} -Properties WhenChanged, LastLogonDate, Description |
Where-Object {$_.WhenChanged -gt $30DaysAgo} |
Select Name, SamAccountName, WhenChanged, LastLogonDate, Description |
Export-CSV "C:\Reports\RecentlyDisabled.csv" -NoTypeInformation
Target specific organizational units when using Get-ADUser disabled queries.
# Get-ADUser enabled false from specific OU
Get-ADUser -Filter {Enabled -eq $false} -SearchBase "OU=Sales,DC=domain,DC=com" -Properties * |
Select-Object Name, Title, Department, LastLogonDate |
Export-CSV "C:\Reports\SalesDisabledUsers.csv" -NoTypeInformation
Active Directory doesn't have a native "DisabledDate" attribute, but you can track when accounts were disabled using these methods:
Method 1: Using WhenChanged attribute
To get-ADUser disabled accounts with approximate disable date:
Get-ADUser -Filter {Enabled -eq $false} -Properties WhenChanged |
Select-Object Name, SamAccountName,
@{Name='ApproxDisableDate';Expression={$_.WhenChanged}},
@{Name='DaysSinceDisabled';Expression={(New-TimeSpan -Start $_.WhenChanged -End (Get-Date)).Days}} |
Export-CSV "C:\Reports\DisabledUsers_WithDates.csv" -NoTypeInformation
Method 2: Find recently disabled users (last 7, 30, or 90 days)
PowerShell get disabled users within specific timeframe:
function Get-RecentlyDisabledUsers {
param([int]$DaysAgo = 30)
$cutoffDate = (Get-Date).AddDays(-$DaysAgo)
Get-ADUser -Filter {Enabled -eq $false} -Properties WhenChanged, LastLogonDate |
Where-Object {$_.WhenChanged -ge $cutoffDate} |
Select-Object Name, SamAccountName,
@{Name='ApproxDisableDate';Expression={$_.WhenChanged}},
@{Name='DaysAgo';Expression={(New-TimeSpan -Start $_.WhenChanged -End (Get-Date)).Days}},
LastLogonDate |
Sort-Object WhenChanged -Descending
}
To get users disabled in last 30 days:
Get-RecentlyDisabledUsers -DaysAgo 30 |
Export-CSV "C:\Reports\RecentlyDisabled.csv" -NoTypeInformation
Exporting disabled users to CSV is essential for reporting, auditing, and compliance.
Get-ADUser -Filter {Enabled -eq $false} -Properties DisplayName, EmailAddress, Department, LastLogonDate |
Select-Object Name, SamAccountName, DisplayName, EmailAddress, Department, LastLogonDate |
Export-CSV "C:\Reports\DisabledUsers.csv" -NoTypeInformation
Write-Host "Export complete. File saved to C:\Reports\DisabledUsers.csv" -ForegroundColor Green
| Parameters | Description |
|---|---|
| -Filter | Specifies criteria using PowerShell Expression Language |
| -SearchBase | Specifies the OU or container to search |
| -SearchScope | Defines search depth (Base, OneLevel, Subtree) |
| -Properties | Specifies additional attributes to retrieve |
| -LDAPFilter | Uses LDAP query syntax for filtering |
| -Server | Specifies the domain controller to query |
Both commands retrieve disabled users, but they work differently:
Get-ADUser provides more flexibility with custom filters and property selection:
Get-ADUser -Filter {Enabled -eq $false -and Department -eq "IT"} -Properties *
Search-ADAccount is optimized for account status queries with built-in options:
Search-ADAccount -AccountDisabled -UsersOnly -AccountInactive -TimeSpan 90.00:00:00
Search-ADAccount is generally faster for simple disabled account queries, while Get-ADUser provides more granular control over filtering and properties.
There's no direct WhenDisabled attribute, but you can use these approaches:
Method 1: Check WhenChanged attribute (includes any modification)
Get-ADUser -Filter {Enabled -eq $false} -Properties WhenChanged |
Select Name, WhenChanged
Method 2: Search Security Event Logs for account disable events (Event ID 4725)
Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4725} |
Select TimeCreated, Message
Method 3: Use replication metadata for more accuracy
Get-ADReplicationAttributeMetadata -Object (Get-ADUser "username").DistinguishedName -Properties userAccountControl
Common issues and solutions:
Syntax errors: Ensure you're using curly braces for script blocks
Correct script:
Get-ADUser -Filter {Enabled -eq $false}
Incorrect script:
Get-ADUser -Filter "Enabled -eq $false"
Module not imported: Import the AD module first
Import-Module ActiveDirectory
Permission issues: Verify you have read permissions on the target OUs.
Wrong domain: Specify the correct domain controller:
Get-ADUser -Filter {Enabled -eq $false} -Server "DC01.domain.com"
Use nested queries to retrieve manager information:
$disabledUsers = Get-ADUser -Filter {Enabled -eq $false} -Properties Manager, EmailAddress
$report = foreach ($user in $disabledUsers) {
if ($user.Manager) {
$managerInfo = Get-ADUser $user.Manager -Properties EmailAddress
[PSCustomObject]@{
UserName = $user.Name
UserEmail = $user.EmailAddress
ManagerName = $managerInfo.Name
ManagerEmail = $managerInfo.EmailAddress
}
}
}
$report | Export-CSV "C:\DisabledUsersWithManagers.csv" -NoTypeInformation
No, Get-ADUser only retrieves user objects. For disabled computers, use Get-ADComputer:
For disabled computers:
Get-ADComputer -Filter {Enabled -eq $false} -Properties LastLogonDate
For both users and computers:
Get-ADObject -Filter {(ObjectClass -eq "user" -or ObjectClass -eq "computer") -and Enabled -eq $false}
Combine multiple conditions in your filter:
$90DaysAgo = (Get-Date).AddDays(-90)
Method 1: Using Get-ADUser
Get-ADUser -Filter {Enabled -eq $false} -Properties LastLogonDate |
Where-Object {$_.LastLogonDate -lt $90DaysAgo -or $_.LastLogonDate -eq $null}
Method 2: Using Search-ADAccount
Search-ADAccount -AccountDisabled -UsersOnly -AccountInactive -TimeSpan 90.00:00:00