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.
Here is the code: