Disable and remove inactive accounts in Active Directory

Quite a few companies don’t have proper account management software to maintain their users in Active Directory . Accounts that remain active while the employees already left the company can be a security risk. This little script will disable and remove inactive accounts.

<#
.SYNOPSIS
    Disable and remove inactive user accounts from Active Directory

.DESCRIPTION
    This script queries active directory to locate user accounts that have not been active for x days.
    Currently the script is wired to do the following:
        a) Disable user accounts that have been inactive for x days
        b) Remove user accounts that have been disabled for x days

    To get this to work, you need to do the following:
        - Run the script as a domain administrator, or with an account that has the privilege to disable and remove accounts
        - PowerShell needs to run as administrator

.EXAMPLE
    .\Cleanup-ActiveDirectory.ps1 -DisableDays 90 -RemoveDays 180

.NOTES
    Version:        0.1
    Author:         Peter The Automator
    Website:        https://petertheautomator.com
#>
Param (
    [parameter(Mandatory)][ValidateRange(90,365)][int]$DisableDays,
    [parameter(Mandatory)][ValidateRange(90,365)][int]$RemoveDays
)

#Get dates for current date minus a bunch of days
[datetime]$DisableDate = (get-date).AddDays(-$DisableDays)
[datetime]$RemoveDate = (get-date).AddDays(-$RemoveDays)

#Get all the users and service accounts
[array]$ExcludedAccounts = "Administrator","Guest","krbtgt","HelpAssistant" #Excluded accounts
Try {
    $Users = Get-ADUser -Filter * -Properties Name,SamAccountName,LastLogonDate,Enabled,WhenChanged
} Catch {
    Write-Error "Failed to find AD accounts. Error: '$($_.Exception.Message)'."
	exit 1
}

#Disable all accounts that have not ben used during the last x days
Try {
    $DisableUsers = $Users | Where-Object {($_.lastlogonDate -le $DisableDate) -and ($_.Enabled -eq $True) -and ($ExcludedAccounts -notcontains $_.SamAccountName)} | Sort-Object Name
    If ($DisableUsers) {
        Write-Host "Disabling $($DisableUsers.Count) users:"
        $DisableUsers | Select-Object Name,SamAccountName,LastLogonDate,WhenChanged
        $DisableUsers | Disable-ADAccount
    }
} Catch {
    Write-Error "Failed to disable the accounts. Error: '$($_.Exception.Message)'."
	exit 1
}

#Remove users that have been disabled for x days
Try {
    $RemoveUsers = $Users | Where-Object {($_.WhenChanged -le $RemoveDate) -and ($_.Enabled -eq $False) -and ($ExcludedAccounts -notcontains $_.SamAccountName)} | Sort-Object Name
    If ($RemoveUsers) {
        Write-Host "Removing $($RemoveUsers.Count) users:"
        $RemoveUsers | Select-Object Name,SamAccountName,LastLogonDate,WhenChanged
        $RemoveUsers | Remove-ADUser
    }
} Catch {
    Write-Error "Failed to remove the accounts. Error: '$($_.Exception.Message)'."
	exit 1
}

The script performs the following actions:
– Disable accounts that have not been active for x days.
– Remove accounts that have been disabled and untouched for x days.

I have added an exclusion list for accounts that are default within Active Directory. It can be extended by custom accounts if needed.

Disclaimer: This script is capable of doing serious harm to your environment. Using this script is your own responsibility.