Hey, Scripting Guy! We have had a number of changes at our company recently. As a result, our Active Directory Domain Services (AD DS) installation is somewhat shabby. Okay, a lot shabby. When I go into AD DS Users and Computers and look through it, I cannot tell which computers are supposed to be there or not. How can I get rid of all the old computer accounts that still reside in AD DS?
– MS
Hi MS,
That is the problem with computer accounts. They get created and are often associated with a specific user. Then the user goes to somewhere like the Cayman Islands to go scuba diving. While the user is down there, he is having all kinds of fun, is relaxed, and begins to think, “You know, if I watched my money, I could live down here and make a living as a scuba instructor. I could get paid to go scuba diving”:
Okay, I’m back. I was reliving my dive when I took that picture. The water was 80 degrees Fahrenheit (26.67 Celsius), visibility was over 100 feet (30.48 meters), and I was gliding along like a seal. Sigh.
Because I came back from the Cayman Islands and did not decide to become a full-time scuba instructor, here is a script you can use to find those users who “forgot” to return:
$maxOldLogonDays = 60 $adsiSearcher = new-object DirectoryServices.DirectorySearcher("LDAP://rootdse") $adsiSearcher.filter = "objectCategory=Computer" $adsiSearcher.findall() | Foreach-Object ` { "Processing $($_.path)" $rawLogon = $_.properties.item("lastlogon") $convertedLogOn = [datetime]::FromFileTime([int64]::Parse($rawLogon)) If( ((get-date) - $convertedLogOn).days -ge $maxOldLogonDays ) { "$($_.properties.item('distinguishedName')) has not logged on for more than $maxOldLogonDays days" } #end if } #end foreach
We begin the script with creating a variable $maxOldLogonDays and setting it equal to 60. (Also see an example of working with the lastlogon attribute in VBScript.) We will use this to filter out the computer objects that are returned based upon our query:
$maxOldLogonDays = 60
Now we need to search AD DS. (Also see an example of searching for computer accounts using VBScript.) To do this, we have several options. We can use ADO as the VBScript example does, or we can use the System.DirectoryServices.DirectorySearcher .NET Framework class.
In Windows PowerShell 2.0 this class has an alias of [adsiSearcher], and you do not need to use the new-object cmdlet to create an instance. The code we are using here will work on both Windows PowerShell 2.0 and on Windows PowerShell 1.0.
When we use the New-Object cmdlet to create an instance of the DirectorySearcher class, we give it “LDAP://rootdse” for the constructor. (The DirectorySearcher class is documented here.) A constructor is used when we create an instance of a class. What this is saying is that we want to search the rootdse using the LDAP protocol:
To translate the lastlogon attribute, we can use the FromFileTime static method from the system.datetime class. We also use the static method parse from the system.int64 class and give it the value we stored in the $rawLogon variable. We save the converted datetime object into the $convertedLogOn variable. This is seen here:
$convertedLogOn = [datetime]::FromFileTime([int64]::Parse($rawLogon))
Once we have done this, we need to evaluate our date to see if it is less than the maximum old logon days value that we stored in the $maxOldLogonDays variable. The cool thing is that we can easily subtract datetime values. Here is an article that talks about working with dates in VBScript. If our lastlogon time is less than a specific number of days old, nothing happens:
If( ((get-date) - $convertedLogOn).days -ge $maxOldLogonDays ) {
If, however, the lastlogon time is greater than the number of days, we print out the distinguished name as seen here:
"$($_.properties.item('distinguishedName')) has not logged on for more than $maxOldLogonDays days" } #end if } #end foreach
MS, I hope you can use this script to help you find all your missing users. If you do contact them, tell them that I am a certified assistant scuba instructor and would be glad to help them with their dives. See you tomorrow.
Ed Wilson and Craig Liebendorfer, Scripting Guys
0 comments