PowerShell: Active Directory Cleanup – Part 3 – Stale Computer Objects

Introduction

Hello everyone. Part 3 in my AD Cleanup series is stale computer objects. Stale computer objects are computers that haven’t logged into the domain for a specified number of days. This script includes a NumberOfDays parameter that either you specify when calling the script or it defaults to 120 days during script execution. The reason for this parameter is some companies may consider a computer stale in 30 days while others consider a computer stale after a longer period such as 120 days. Think about a company with lots of remote workers who rarely connect to the corporate network. Although they may be active every day the network may not see them for weeks or months at a time.

Stale Computer Objects

Function Get-StaleComputers {
    <#
        .SYNOPSIS
        This Function searches Active Directory for stale computer objects.
        
        .DESCRIPTION
        This Function searches Active Directory for stale computer objects based on the NumberOfDays parameter. It checks both the LastLogonDate and PasswordLastSet attributes against NumberOfDays.

        .PARAMETER NumberOfDays
            The number of days old a computer object is to be considered stale.  Default is 120 days.

        .PARAMETER ExportToCSV
            If specified location and CSV file to output the results. Default is the script directory location and a file named StaleComputers_yyyyMMss.csv.

        .EXAMPLE
        Get-StaleComputers

        Returns Stale computers using the default values of 120 Days and writes a csv file to the scripts execution location.
        Number Of Days: 120
        Export To CSV : C:\Scripts\StaleComputers_20200106.csv

        .EXAMPLE
        Get-StaleComputers -NumberOfDays 180

        Returns Stale computers using the value of 180 Days and writes a csv file to the scripts execution location.
        Number Of Days: 180
        Export To CSV : C:\Scripts\StaleComputers_20200106.csv

        .EXAMPLE
        Get-StaleComputers -NumberOfDays 180

        Returns Stale computers using the value of 180 Days and writes a csv file to the scripts execution location.
        Number Of Days: 180
        Export To CSV : C:\Scripts\StaleComputers_20200106.csv    

        .EXAMPLE
        Get-StaleComputers -NumberOfDays 180 -ExportToCSV c:\Reports\StaleComputers.csv

        Returns Stale computers using the value of 180 Days and writes a csv file to C:\Reports\StaleComputers.csv.
        Number Of Days: 180
        Export To CSV : c:\Reports\StaleComputers.csv
    #>

    [CmdletBinding()]
    param(
        # # of days ago to purge
        [int] $NumberOfDays = 120,
        # Specifies to export to the specified csv file
        [String] $ExportToCSV = $($PSScriptRoot + "\StaleComputers_" + $(Get-Date -Format yyyyMMdd) +".csv")
    )

    # Computer Variable Initializations
    Write-Verbose -Message "Initializing Variables."
    $DaysAgo = 0 - $NumberOfDays
    $AllADComputerObjects = $null 
    Write-Output "Number Of Days: $NumberOfDays"
    Write-Output "Export To CSV : $ExportToCSV"

    # Computer Properties List
    Write-Verbose -Message "Set Property Variables."
    $ComputerPropsAll = $("Name","SamAccountName","Enabled","OperatingSystem","OperatingSystemServicePack","IPv4Address","LastLogonDate","PasswordLastSet","Modified","canonicalname","DistinguishedName","whenChanged","whenCreated")
    $ComputerPropsPlusCreator = $("Name","SamAccountName","Enabled","OperatingSystem","OperatingSystemServicePack","IPv4Address","LastLogonDate","PasswordLastSet","Modified","canonicalname","DistinguishedName","whenChanged","whenCreated",@{Name="CreatedBy";Expression={$(([ADSI]"LDAP://$($_.DistinguishedName)").psbase.ObjectSecurity.Owner)}})

    # Gather Computer Data from Active Directory and Analyze
    Write-Verbose -Message "Querying Active Directory for Computer Objects..."  
    $AllADComputerObjects = (Get-ADComputer -Filter * -Properties $ComputerPropsAll)

    Write-Verbose -Message "Searching Active Directory for Stale ($DaysAgo Days) Computers."
    $StaleDate = (Get-Date).AddDays($DaysAgo)
    $StaleComputers = ($AllADComputerObjects | ? {$_.PasswordLastSet -le $StaleDate -and $_.LastLogonDate -le $StaleDate}) | Select-Object $ComputerPropsPlusCreator
    If ($StaleComputers) {
        $StaleComputers | Export-Csv -Path $ExportToCSV -NoTypeInformation -Force
        Write-Output "Stale Computers Found: $($StaleComputers.count)"
        Write-Output "Output was sent to $ExportToCSV"
    } Else {
        Write-Output "No Stale Computers Found."
    }
}
cls
Get-Help Get-StaleComputers -Full

Examples

# Below are some examples of script execution
        .EXAMPLE
        Get-StaleComputers
 
        Returns Stale computers using the default values of 120 Days and writes a csv file to the scripts execution location.
        Number Of Days: 120
        Export To CSV : C:\Scripts\StaleComputers_20200106.csv
 
        .EXAMPLE
        Get-StaleComputers -NumberOfDays 180
 
        Returns Stale computers using the value of 180 Days and writes a csv file to the scripts execution location.
        Number Of Days: 180
        Export To CSV : C:\Scripts\StaleComputers_20200106.csv
 
        .EXAMPLE
        Get-StaleComputers -NumberOfDays 180
 
        Returns Stale computers using the value of 180 Days and writes a csv file to the scripts execution location.
        Number Of Days: 180
        Export To CSV : C:\Scripts\StaleComputers_20200106.csv    
 
        .EXAMPLE
        Get-StaleComputers -NumberOfDays 180 -ExportToCSV c:\Reports\StaleComputers.csv
 
        Returns Stale computers using the value of 180 Days and writes a csv file to C:\Reports\StaleComputers.csv.
        Number Of Days: 180
        Export To CSV : c:\Reports\StaleComputers.csv

Summary

Notice in this script I added help, parameters, parameter defaults, property arrays and examples. I made it into function so it can be added to larger scripts. I recommend to write it as a normal script then when you’ve ironed out any bugs add the function name {} around the script. The last line “Get-Help Get-StaleComputers -Full” displays the help for the function. Remove this line and replace with the function name and the parameters as shown in the help and Examples above.

Series Links: