How to find computer accounts that are no longer needed in AD

I am new to this position and find it's AD structure in need of a serious cleaning. There are over twice as many computer accounts as there are employees, not even taking into account servers. I'd like to be able to know which of them are still valid and which can be deleted without repercussion.

I found the tool from Joeware, OldComp, it looks pretty handy but I guess I'm just needing a bit more understanding of what it's looking at...when it searches for computers more than 90 days old, does that mean it's been 90 days since it was plugged in to the network? The reason behind this is, I don't want to inadvertently disjoin a laptop from a field office that may be on a shelf as a backup, thinking it's an "old" computer when really it's just not plugged in and being used currently. Maybe it's not worth worrying about for the rare chance that might happen though...

Anyway, if anyone knows of any other way or has a good example of how best to accomplish this I would appreciate some insight. The end result is I'd just like to be able to get rid of computer accounts no longer being used. Thanks.


Solution 1:

Oldcmp is well known for what it does and will work fine for first time and occasional cleanup.
If, over time, you want an automated process, you can use Powershell (highly recommended) to write an automated process for this. For instance, Our current script does the following:

  • Locates old accounts based on lastLogonTimeStamp using get-ADcomputer
  • disables them after 60 days
  • deletes them after 90 days
  • Logs everything it does

In addition, we use the ProtectFromAccidentialDeletion flag on the account if we don't want it deleted.

Solution 2:

There isn't any method that's going to be able to distinguish between a machine that is gone and doesn't exist any longer and one that is sitting on a shelf unused so use OldComp to do the cleanup and deal with the one-offs if and when they come up.

Solution 3:

Why not PowerShell?

    $Computers =  ([ADSISearcher]"(&(objectCategory=computer)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))").FindAll()
    $Computers = $Computers | ForEach { $_.Path }
    $Age = $(Get-Date).AddDays(-90)

    $StaleComputerAccounts = @()
    $NeverUsedComputerAccounts = @()


    ForEach ($Computer in $Computers) {

        $ComputerObj = [ADSI]$Computer


        if ($ComputerObj.lastLogon) {

            $LastLogon = [DateTime]::FromFileTime($ComputerObj.ConvertLargeIntegerToInt64($ComputerObj.lastlogon[0]))
            if ( $LastLogon -lt $Age ) {

                $StaleComputerAccounts += $Computer

            }

        }
        else {

            $NeverUsedComputerAccounts += $Computer

        } 

}


You should end up with a list of $StaleComputerAccounts and $NeverUsedComputerAccounts which you can then manipulate with more PowerShell. I like doing something like this:

$TargetOU = "OU=Computers,OU=Disabled,OU=,DC=CONTOSO,DC=com"
$OUObj = [ADSI]"LDAP://$TargetOU"


ForEach ($Computer in $StaleComputerAccounts) {

    $ComputerObj = [ADSI]$Computer
    $ComputerObj.PSBase.MoveTo($OUObj)
    $ComputerObj.InvokeSet("accountDisabled", $True)
    $ComputerObj.SetInfo()

}



There's no magical way to programatically distinguish between a computer that has been improperly decommissioned (no one removed it from Active Directory when it was off-lined) and a laptop sitting in some executive's desk. If you want to move carefully you can just disable the account and send it off to a specific OU like I do.