<# .SYNOPSIS Lists all Active Directory users who have not logged on for more than 90 days (default) and are not disabled. .DESCRIPTION Uses Active Directory cmdlets to find all users and checks their last logon date. Users who have had no active logon for longer than the configured number of days (default 90) are returned. .PARAMETER Days Number of days after which a user is considered inactive. Defaults to 90. .PARAMETER IncludeDisabled If set, the script also includes DISABLED users in the results. .PARAMETER SearchBase If set, the script searches for users only within the specified OU(s). This is an array, so multiple OUs can be supplied; each one is searched recursively and the results are combined. .EXAMPLE .\Get-InactiveUsers.ps1 Displays users who have not been active for more than 90 days. .EXAMPLE .\Get-InactiveUsers.ps1 | Sort-Object LastLogonDate | Format-Table -AutoSize Displays users who have not been active for more than 90 days, sorted by last logon date. .EXAMPLE .\Get-InactiveUsers.ps1 -Days 180 Displays users who have not been active for more than 180 days. .EXAMPLE .\Get-InactiveUsers.ps1 -Days 365 -IncludeDisabled Displays users who have not been active for more than 365 days, including DISABLED users. .EXAMPLE .\Get-InactiveUsers.ps1 -SearchBase "OU=Users,DC=example,DC=com" Displays users who have not been active for more than 90 days, searching only within the specified OU. .EXAMPLE .\Get-InactiveUsers.ps1 | Export-Csv -Path .\Export_InactiveUsers.csv -NoTypeInformation -Encoding UTF8 Exports all inactive users in Active Directory to a CSV file. .EXAMPLE .\Get-InactiveUsers.ps1 | Set-ADUser -Enabled $false Disables all inactive users in Active Directory. .NOTES Author: Petr Štěpán Created: 2024-10-20 Version: 1.1.0 Changelog: 1.1.0 - Fixed -SearchBase to correctly support multiple OUs (Get-ADUser's own -SearchBase only accepts one); added standard header, Set-StrictMode/$ErrorActionPreference, error handling, exit codes. 1.0.0 - Initial version #> #Requires -Modules ActiveDirectory [CmdletBinding()] param ( [Parameter(Mandatory = $false, HelpMessage = 'Number of days after which a user is considered inactive.')] [ValidateRange(15, [int]::MaxValue)] [int] $Days = 90, [Parameter(Mandatory = $false, HelpMessage = 'Also include DISABLED users?')] [switch] $IncludeDisabled, [Parameter(Mandatory = $false, HelpMessage = 'Search for users only within the specified OU(s).')] [ValidateNotNullOrEmpty()] [string[]] $SearchBase ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' # Read-only script (queries Active Directory only) - no ShouldProcess needed. # The caller decides what to do with the results (export, disable, ...) via the pipeline. $propertiesToRetrieve = 'Name', 'SamAccountName', 'LastLogonDate', 'Enabled', 'PasswordNeverExpires', 'CanonicalName', 'DistinguishedName' # Date beyond which a user is considered inactive $inactiveDate = (Get-Date).AddDays(-$Days) if ($IncludeDisabled) { $parameters = @{ Filter = { LastLogonDate -le $inactiveDate } } } else { $parameters = @{ Filter = { LastLogonDate -le $inactiveDate -and Enabled -eq $true } } } if ($SearchBase) { # Get-ADUser's own -SearchBase only accepts a single OU, so each requested # OU is queried separately and the results are combined. $inactiveUsers = [System.Collections.Generic.List[object]]::new() $failedOuCount = 0 foreach ($ou in $SearchBase) { Write-Verbose "Searching for inactive users in OU '$ou'..." try { $ouUsers = Get-ADUser @parameters -SearchBase $ou -Properties $propertiesToRetrieve -ErrorAction Stop foreach ($u in $ouUsers) { $inactiveUsers.Add($u) } } catch { Write-Warning "Skipping OU '$ou': failed to query users - $_" $failedOuCount++ } } if ($failedOuCount -eq $SearchBase.Count) { Write-Error "Failed to retrieve users from any of the specified OUs." exit 1 } } else { Write-Verbose "Searching for inactive users across the entire domain..." try { $inactiveUsers = @(Get-ADUser @parameters -Properties $propertiesToRetrieve -ErrorAction Stop) } catch { Write-Error "Failed to query inactive users from Active Directory: $_" exit 1 } } $inactiveUsers | Select-Object -Property $propertiesToRetrieve exit 0