PKAdcComputer.psm1
function Get-PKAdcComputer { <# .SYNOPSIS ADCleanup for ADComputers. Get-PKAdcComputer will only retrieve data and specify what Action to take but no changes are made. .DESCRIPTION If Computer is Enabled and LastLogonDate is older than DisableDays, the Action is Disable. If Computer is Disabled and older than RemoveDays, the Action is Remove. If the OS is like *Server* or Unknown, it is skipped. To exclude the computer and set the Action to Keep. Add Keep to the computer description. Input Parameters require positive integers Output Object with the following Properties: ComputerName Enabled Action - Disable Wait Remove None Keep LastLogonDate OperatingSystem Description .EXAMPLE Get-PKAdcComputer <computer> | ? {($_.Action -ne 'None')} Gets the computers and displays Action. None is taken. Display Objects with Action not equal to None .EXAMPLE Send-PKAdcComputer A report is emailed but no Action is taken .EXAMPLE Get-ADComputer -Filter * | Get-PKAdcComputer | Remove-PKAdcComputer Gets the computers and applies the Action. No Output. #> [CmdletBinding()] param( [Parameter(Mandatory,ValueFromPipeline)] [string[]]$ComputerName, [ValidatePattern('^[1-9]')] [int]$DisableDays = 30, [ValidatePattern('^[1-9]')] [int]$RemoveDays = 30 ) BEGIN { $DisableDate = (Get-Date).AddDays(-$DisableDays) $RemoveDate = (Get-Date).AddDays(-$RemoveDays) #Combines days and used if computer is manually disabled without a date in the description $NoDescRemoveDate = (Get-Date).AddDays(-$DisableDays-$RemoveDays) } PROCESS { foreach ($Computer in $ComputerName) { try { $Comp = Get-ADComputer $Computer -Properties LastLogonDate,Description,OperatingSystem -ea Stop } catch { Write-Warning $_ continue } #Logic to process servers and unknown OS can be added in the future if ($Comp.OperatingSystem -like '*server*' -or $Comp.OperatingSystem -eq $null) { Write-Verbose "$Computer is a server or unknown, continue to next computer" continue } if ($Comp -ne $null) { if ($Comp.LastLogonDate -lt $DisableDate) { if ($Comp.Enabled) { Write-Verbose "$($Comp.Name) Enabled, LastLogonDate older than DisableDate" $Action = 'Disable' } else { try { $DescDate = [datetime]$Comp.Description.Trim("INACTIVE ").Split()[0] if ($DescDate -lt $RemoveDate) { Write-Verbose "$($Comp.Name) Disabled, DescriptionDate older than RemoveDate" $Action = 'Remove' } else { Write-Verbose "$($Comp.Name) Disabled, DescriptionDate not old enough to Remove yet" $Action = 'Wait' } } catch { if ($Comp.LastLogonDate -lt $NoDescRemoveDate) { Write-Verbose "$($Comp.Name) Disabled, No DescriptionDate, LastLogonDate older than combined Disable Remove Date" $Action = 'Remove' } else { Write-Verbose "$($Comp.Name) Disabled, No DescriptionDate, LastLogonDate not old enough to Remove yet from combined Disable Remove Date" $Action = 'Wait' } } } } else { Write-Verbose "$($Comp.Name) Active, LastLogonDate not older than DisableDate" $Action = 'None' } if ($Comp.Description -like '*KEEP*') { Write-Verbose "$($Comp.Name) Description Keep, Overrides all Actions" $Action = 'Keep' } [PSCustomObject]@{ ComputerName=$Comp.Name Enabled=$Comp.Enabled Action=$Action LastLogonDate=$Comp.LastLogonDate OperatingSystem=$Comp.OperatingSystem Description=$Comp.Description } } } } } function Remove-PKAdcComputer { [CmdletBinding()] param( [Parameter(Mandatory,ValueFromPipeline)] [psobject]$InputObject ) BEGIN { $Description = "INACTIVE $(Get-Date -f d)" } PROCESS { foreach ($Computer in $InputObject) { Switch ($Computer.Action) { Disable { Write-Verbose "$($Computer.ComputerName) processing Disable: Remove ProtectedFromAccidentalDeletion, Disable, Update Description" Get-ADComputer $Computer.ComputerName | Set-ADObject -ProtectedFromAccidentalDeletion $false -Confirm:$false Set-ADComputer $Computer.ComputerName -Enabled $false -Description "$Description $($Computer.Description)" -Confirm:$false } Remove { Write-Verbose "$($Computer.ComputerName) processing Remove: Remove-ADComputer" Remove-ADComputer $Computer.ComputerName -Confirm:$false } Default { Write-Verbose "$($Computer.ComputerName) Nothing to process" } } } } } function Send-PKAdcComputer { [CmdletBinding()] param( [string]$SmtpServer = 'smtp-relay.gmail.com', [string]$From = 'Email <user@domain.com>', [string[]]$To = @('user@domain.com','user@domain.com'), [string]$Subject = 'ADCleanup Report: Windows Computers' ) BEGIN {if (!(Get-Module EnhancedHTML2)) {Import-Module EnhancedHTML2}} PROCESS { $style = @" <style> body { color:#333333; font-family:Calibri,Tahoma; font-size: 10pt; } h1 { text-align:center; } h2 { border-top:1px solid #666666; } hr { height:1px; border-width:0; background-color:gray; } th { font-weight:bold; color:#eeeeee; background-color:#333333; padding:4px; } .odd { background-color:#ffffff; } .even { background-color:#dddddd; } .dataTables_info { margin-bottom:4px; } .grid { width:100% } .red { text-align:right; font-weight:bold; color:red; } .bold { text-align:right; font-weight:bold; } .right { text-align:right; } </style> "@ $params = @{'As'='Table'; 'PreContent'="<h2>♦ ADCleanup Computers</h2>The 'Action' has been applied to the following computers.<br>Add KEEP in the Description to exclude from ADCleanup.<br>Default: Disable inactive after 30 days, Remove disabled after 30 days." 'EvenRowCssClass'='even'; 'OddRowCssClass'='odd'; } $html_PKAdcComputer = Get-ADComputer -Filter {OperatingSystem -like 'Windows*'} | Get-PKAdcComputer | Where {$_.Action -ne 'None'} | sort Action,ComputerName | ConvertTo-EnhancedHTMLFragment @params $params = @{'CssStyleSheet'=$style; 'Title'=$Subject; 'PreContent'="<h1>$Subject</h1>"; 'PostContent'="<br><hr /><i>Created $(Get-Date)</i>"; 'HTMLFragments'=@($html_PKAdcComputer)} $Body = ConvertTo-EnhancedHTML @params Send-MailMessage -SmtpServer $SmtpServer -From $From -To $To -Subject $Subject -Body ($Body | Out-String) -BodyAsHtml } } function Use-PKAdcComputer { Send-PKAdcComputer Get-ADComputer -Filter {OperatingSystem -like 'Windows*'} | Get-PKAdcComputer | Remove-PKAdcComputer } function Register-PKAdcComputer { $Cred = Get-Credential -Message 'Account used to run Scheduled Task.' if ($Cred) { $params = @{ Action=New-ScheduledTaskAction -Execute 'powershell.exe' -Argument 'Use-PKAdcComputer' Trigger=New-ScheduledTaskTrigger -Weekly -DaysOfWeek Tu -At 10am User=$Cred.UserName Password=$Cred.GetNetworkCredential().Password TaskName='PKAdcComputer' Description='Disable/Remove stale AD Computer Objects and email report. Windows Only. -PKADCleanup' RunLevel='Highest' } Register-ScheduledTask @params -Force } } |