Script to find outdated computer objects in Active Directory

Computers have accounts in Active Directory and log on just as user accounts do. The “user name” of a computer is its name with a dollar sign appended, e.g: MYPC1$. The password is set by the machine when it is joined to the domain and changed every 30 days by the machine. Just as with user accounts, computer accounts gets left in the domain when the machine is decomissioned or reinstalled under another name etc. This leaves our directory service full of outdated user and computer object. (Outdated in this context means “has not logged on to the domain for X days). This in turn makes it hard to know how many computers are actually active. So how to battle this problem?

On Windows 2000 every DC maintend an attribute on each computer object called lastLogon. It stored the timestamp of the last logon for a computer on that DC. The “on that DC” part is important, because the lastLogon attribute was not replicated beyond the local DC. So to figure out when computer CORP-PC1 last logged on, you would have to query the lastLogon attribute on all the DCs in the domain and find the most recent one. This could be done, but was tedious and time consuming. Enter Windows Server 2003.

In Windows Server 2003 a new attribute was introduced; lastLogonTimestamp. Just like lastLogon, lastLogonTimestamp stored the timestamp of the last logon to the domain for a computer account, but lastLogonTimestamp is a replicated attribute, which means that now every DC knows the most recent logon time for a computer. So to figure out when CORP-PC1 last logged on to any DC in the domain we can query any DC for the lastLogonTimestamp attribute of CORP-PC1. Very nice.

I often find myself in a situation where I need to “clean house” in customer’s directories so I created a script that uses lastLogonTimestamp to find all computers that have not logged on to the domain for X days. X varies greatly from customer to customer, but a good start would be 90 days. The sciprt is called FindOutdatedComputers.vbs and in this post I would like to share it with you.

FindOutdateComptuers.vbs has 3 user changeable variables: intTimeLimit, strDomain and strDC. These are defined at the very beginning of the code and should be the only variables you change.

intTimeLimit: the number of days since a computer logged on to the domain

strDomain: LDAP domain name; e.g. dc=mydomain,dc=com

strDC: FQDN of DC in domain; e.g. dc1.mydomain.com

The script must be run with cscript.exe and takes one command line argument; a 0 (zero) or a 1 (one). 0 mens just echo out the machines that have not logged on since the defined limit and 1 means echo out, but also move the comptuters to the Outdated Computer Objects OU (which the script creates). It will never delete any information from your AD, only move computer accounts to the Outdated Comptuer Objects OU. If you omit this argument, the default action is just to display the results and not move anything.

For FindOutdatedComptuers.vbs to work your domain functional level must be at least Windows Server 2003. The script checks for this and warns you if you are below the needed level.

Strange, have not seen that before for DCs. To figure out what is going on you can examine the value of the lastLogonTimestamp on your DCs manually. The latest version of ADUC or ADSIEdit should convert the values into human readable form for you.

Great Script!
Used on one of my customers that had a messy AD.
Used the move to ou option, and with little effort I could identify the remaining computers (except one) and delete the rest. Saved me about 2 hours of manual labor. To bad I cant invoice those “lost” hours 😀

Hey I need this script………
I’m a little weak on the scripting. Quick question…. How can I run this against only my “Workstations” OU only. I recently started in this position and I have a script that will find 90,60 day outdated devices but I don’t have one to move them and for now I need restrict it only move those outdated computers in my Workstation OU

Absolutely, but I was planning to convert it to PowerShell pretty soon, and then it will be even easier. Basically to change the current script you would need to edit the LDAP query string to return user objects instead of computers.