Add Get-InactiveUsers script to list Active Directory users inactive for over 90 days
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
<#
|
||||
.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
|
||||
Reference in New Issue
Block a user