• Some users have recently had their accounts hijacked. It seems that the now defunct EVGA forums might have compromised your password there and seems many are using the same PW here. We would suggest you UPDATE YOUR PASSWORD and TURN ON 2FA for your account here to further secure it. None of the compromised accounts had 2FA turned on.
    Once you have enabled 2FA, your account will be updated soon to show a badge, letting other members know that you use 2FA to protect your account. This should be beneficial for everyone that uses FSFT.

Cool "cleaning" tool for active directory

YeOldeStonecat

[H]F Junkie
Joined
Jul 19, 2004
Messages
11,330
Working on a server..heck..the entire network on this disaster unkempt project....

Ever come across a server..decent sized network..see TONS of computer accounts in ADUC...and you know many of them are.."stale". Probably the prior techs never "removed" the computer account when replacing the workstation.

I'm mopping up a cranky server before bringing in a new domain controller to this existing network...and wanting to clean things up....stumbled upon this "free" utility..

http://www.download.com/Active-Directory-Cleaner/3000-2651_4-10820300.html

Appears to have just come out a month ago. Requires .NET Framework 3.5 though. I installed 3.5 on a workstation...and this tool..logged in as domain admin..fired up the utility...BAM...instant list of computers in active directory, their SIDs, and importantly...last login date. (Free tool so didn't want to install on a server..nor did I want to install .NET 3.5 on a server) Which..due to the hideous manner of how the prior IT guy named the workstations (something like User-345657 or ODD-4r5t6y7)....instead of easier methods like some sort of position/department/etc manner....

Anyways...thought I'd post this for peeps bag of tricks.
 
That's cool, but I don't see why it requires .net 3.5. At the root, it's just an LDAP query for computer objects and converts last logon timestamps to a human readable format. I'd prefer it as a vbs as opposed to needing a whole app for it.
 
That's cool, but I don't see why it requires .net 3.5. At the root, it's just an LDAP query for computer objects and converts last logon timestamps to a human readable format. I'd prefer it as a vbs as opposed to needing a whole app for it.

I agree...it can really hamper what you want to install it on...I'm always leery of installing some new version of .NET. Seen it break so many apps in the past. And that turns into a mightmare to mop up and get the old app which required a prior version of .NET to function again.

The app is very tiny....so I can see why it wants to run on top of framework..but such a new one..yeah...I agree.
 
Hmmmmm, I may give that a shot here in the coming months. I have to help mop up a school district with around 6,000 computers. For the last few years they have been re-ghosting a few schools every year and renaming everything without deleting the old computer accounts. . . . . . .
 
Nice find. I've got a laptop that I've been wiping clean with some Vista testing lately. I can toss it on there and see how it works. :D
 
I was curious to see if I could come up with something after blasting the idea of requiring .net 3.5 to run this task. It's not the prettiest, but it works and has minor error handling. Converting the lastLogonTimestamp took me the longest to figure out; vbscript doesn't handle long integers natively.

Edit ADRoot with your domain root. You can also edit the output directory / filenames.

Import it into excel (tab seperated) and you can sort based on date. It is trivial to edit this to only output accounts with inactivity longer than x so you don't need excel.


Code:
Const ADS_SCOPE_SUBTREE = 2
Const strComputer = "."

'Common Objects
Set objNetwork = CreateObject("WScript.Network")
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand =   CreateObject("ADODB.Command")
Set objFSO = CreateObject("Scripting.FileSystemObject")

objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
ADRoot = "DC=domain,DC=local"
strDirectory = "C:\"
strFile = "output.txt"
strErr = "err.txt"

'Main()
Set colADComputers = ADComputers()

wscript.quit(1)


function ADComputers()

Set objCommand.ActiveConnection = objConnection
objCommand.CommandText = "Select distinguishedName From 'LDAP://" &  ADRoot & "' where objectClass='computer'"  
objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 
Set objRecordSet = objCommand.Execute
objRecordSet.MoveFirst

Set ADComputers = CreateObject("Scripting.Dictionary")
Set fErr = openForWriting(strDirectory, strErr)
Set fOut = openForWriting(strDirectory, strFile)

On Error Resume Next
Do Until objRecordSet.EOF
	DN = objRecordSet.Fields("distinguishedName")
	objQuery = "LDAP://" & DN
	Set objUser = GetObject(objQuery)
	If Err.Number <> 0 Then
		fErr.WriteLine (DN & "	" & Err.Number)
		Err.Number = 0
	Else
	    Set objLastLogon = objUser.Get("lastLogonTimestamp")
	    If VarType(objLastLogon) <> 9 Then
	    	fErr.WriteLine (objRecordSet.Fields("distinguishedName") & VarType(objLastLogon) & " : 1 means null - no recorded logins")
		Else
			intLastLogonTime = objLastLogon.HighPart * (2^32) + objLastLogon.LowPart
			intLastLogonTime = intLastLogonTime / (60 * 10000000)
			intLastLogonTime = intLastLogonTime / 1440
			fOut.WriteLine(DN & "	" & IntLastLogonTime + #1/1/1601#)
		End If 
	End If
    objRecordSet.MoveNext
Loop
On Error Goto 0
End Function

Function openForWriting(Path, Name)
If objFSO.FolderExists(Path) Then
   Set objFolder = objFSO.GetFolder(Path)
Else
   Set objFolder = objFSO.CreateFolder(Path)
End If

If objFSO.FileExists(Path & Name) Then
   Set objFolder = objFSO.GetFolder(Path)
Else
   Set objFile = objFSO.CreateTextFile(Path & Name)
End If

set objFile = nothing
set objFolder = Nothing

Const ForWriting = 2
Set openForWriting = objFSO.OpenTextFile(Path & Name, ForWriting, True)
End Function
 
Correct me if I'm wrong, but I vaguely recall something about the last logon timestamp not being replicated between domain controllers; you'd have to query them all, and them compare results. Am I mistaken, or thinking of something else?
 
Correct me if I'm wrong, but I vaguely recall something about the last logon timestamp not being replicated between domain controllers; you'd have to query them all, and them compare results. Am I mistaken, or thinking of something else?

lastLogon is not replicated. lastLogonTimestamp is new to Server 2003 and is replicated (only every 14 days to reduce replication traffic).
 
it won't let me sort by any of the fields...name, last logon, etc.

bug? not implemented?
 
lastLogon is not replicated. lastLogonTimestamp is new to Server 2003 and is replicated (only every 14 days to reduce replication traffic).

So would this program work on a 2000 domain level? If so I will be trying this out very soon.
 
you'd need to edit it to query both dcs, then keep the newest lastLogon record. might as well try the utility in the op - it's unclear what it uses though.
 
Man the server that brought me to find this utility is a mess. :p Gotta get some ADPREP going soon..just built a new DC to take over the roles....building a separate Exchange server too.

This current server is so bogged down....tons of stale active directory objects, Exchange server with tons of old users mailboxes, SQL server running their time clock (Stromberg), file and print sharing, ROAMING PROFILES (ugh...I've seen some that are over 1 gig in size), an ancient DOS database for their beds and medical billing which hammers the network hard, talk about all the eggs in one basket. :rolleyes:
 
I actually used this yesterday after reading this post. Nice little tool. I only wish you could sort alphabetically instead of having to peruse through the entire list to find an entry. Other than that, nice tool.
 
Back
Top