Active Directory: Cleaning obsolete computer objects

To filter obsolete computer objects properly from Active Directory, I've used lastlogontimestamp attribute.
This attribute may not be as updated as lastlogon, but lastlogon does not replicate between Domain Controllers so you would need to ask to all of them for the real last logon date.
Lastlogontimestamp does replicate, but its date may be 14 days out of sync with the real one.
In my case, I am going to filter computers that has not connected in 100 days, so 14 days of difference doesn't really matter.

function list-obsoletes()
{
$maxOldLogonDays = 100
$now=get-date
$Dom='LDAP://DC=domain,DC=local'
$objDomain   = New-Object System.DirectoryServices.DirectoryEntry $Dom
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.PageSize = 2000
$objSearcher.filter = "(&(objectCategory=Computer))"
$machines=$objSearcher.FindAll()
out-file "obsoletecomputers.csv" -input "NAME OS LASTLOGONTIMESTAMP DAYS PATH"
Foreach($machine in $machines) 
{
$lastlogon=get-date ([DateTime]::FromFileTime([Int64]::Parse($machine.properties.lastlogontimestamp)))
$intTimeInterval = [int32]($now - $lastlogon).days
 if ($intTimeInterval -gt $maxOldLogonDays -and [string]$machine.properties.distinguishedname -notmatch "OU=ObsoleteComputers")
 {
 $ESPlastlogon=get-date ($lastlogon) -uformat "%d/%m/%Y"
 $msg="$($machine.properties.name) $($machine.properties.operatingsystem) $ESPlastlogon $intTimeInterval $($machine.path)"
 out-file "obsoletecomputers.csv" -input $msg -append
 write-host $msg
 }

} #end foreach
}#end function list-obsoletes

function move-computers()
{
$obsoletepath=[ADSI]("LDAP://OU=ObsoleteComputers,CN=Computers,DC=domain,DC=local")
$content=get-content("obsoletecomputers.csv")
foreach ($line in $content)
 {
 $field=$line.split(" ") #tab
 $name=$field[0]
 $path=$field[4]
 write-host "Moving $name to OU of Obsoletes"
 $from = new-object System.DirectoryServices.DirectoryEntry($path)
 $from.MoveTo($obsoletepath)
 }
}#end function move-computers

###main###
write-host "CHECK/CLEAN OBSOLETE COMPUTERS IN ACTIVE DIRECTORY" -fore cyan
Write-host "1. List obsolete computers" -fore cyan
write-host "2. Move obsolete computers" -fore cyan
$val=read-host "Choose an option"

switch ($val)
{
1{list-obsoletes}
2{move-computers}
}#end of switch

I have split the script in two different functions, the first one list the computer names in a csv file and the second one moves the obsolete computers from the list to an organizational unit created for that purpose.
In fact the first function excludes from the list those computers that are already inside that OU.

Comments