' http://morgansimonsen.wordpress.com/2012/02/28/script-to-find-outdated-computer-objects-in-active-directory/ ' FindOutdatedComputers.vbs ' by Morgan Simonsen ' http://morgansimonsen.wordpress.com ' ' This script will search an Active Directory domain for computer accounts that have ' not logged on the domain in the specified time limit (default 60 days). ' ' 600 000 000 100-nanosecond intervals in 1 minute ' 1440 minutes in 24-hours ' 30 * 1440 * 600 000 000 = time in 100-nanosecond intervals since 1.1.1601 ' ' For Windows 2000, Windows XP and Windows Server 2003, the default computer account password change is 30 days, ' on Windows NT-based computers, the machine account password automatically changes every seven days ' ' http://support.microsoft.com/kb/q154501/ ' http://support.microsoft.com/default.aspx?scid=kb;en-us;q175468 ' ' While lastLogon is not replicated between domain controllers, attribute 'lastLogonTimestamp' IS replicated ' between DC's, so we do NOT have to check multiple DC's any more!! However, it is ONLY replicated every 14 ' days, so it's used to find stale accounts. ' http://www.microsoft.com/technet/scriptcenter/topics/win2003/lastlogon.mspx ' ' USAGE: ' cscript.exe CreateListEnabledHosts.vbs |1 only list or list and move objects, default is list only> ' '=========================== ' User changeable variables '=========================== 'Time limit in number of days intTimeLimit = 45 Const adVarChar = 200 Const MaxCharacters = 255 Const ForReading = 1 Const ForWriting = 2 Const ADS_SCOPE_SUBTREE = 2 Const FOR_WRITING = 2 Dim count, strOld, strDomain Set objRootDSE = GetObject("LDAP://RootDSE") Set objArgs = WScript.arguments If objArgs.Count = 0 Then WScript.Echo "No arguments submitted, using default values" strDomain = objRootDSE.Get("defaultNamingContext") Else strDomain = objArgs.item(0) End If WScript.Echo "strDomain=" & strDomain strDC = objRootDSE.Get("dnsHostName") WScript.Echo "strDC=" & strDC strSearchFilter = "(&(objectCategory=computer)" _ & "(operatingSystem=*)" _ & "(!userAccountControl:1.2.840.113556.1.4.803:=2))" strAttributes = "name,distinguishedName,operatingSystemVersion,dNSHostName,operatingSystem" 'Comma separated strLevel = "subtree" 'Set objWSHShell = WScript.CreateObject("WScript.Shell") set objFSO = CreateObject("Scripting.FileSystemObject") If objFSO.FileExists("Serverlist.txt") Then objFSO.DeleteFile("Serverlist.txt") End IF Set objFile = objFSO.CreateTextFile("Serverlist.txt", FOR_WRITING) Dim strFSMOSchemaMaster Dim strFSMOInfrastructureMaster Dim strFSMOPDCEmulator Dim strFSMORIDMaster Dim strFSMODomainNamingMaster 'WScript.Echo "time is:" & Now - #1/1/1601# Set objADODBConnection = CreateObject("ADODB.Connection") objADODBConnection.Provider = "ADsDSOObject" objADODBConnection.Open Set objADODBCommand = CreateObject("ADODB.Command") Set objADODBCommand.ActiveConnection = objADODBConnection objADODBCommand.Properties("Page Size") = 500 'objADODBCommand.CommandText = ";" & strSearchFilter & ";" & strAttributes & ";" & strLevel objADODBCommand.CommandText = ";" & strSearchFilter & ";" & strAttributes & ";" & strLevel Set objRecordSet = objADODBCommand.Execute count = 0 While Not objRecordset.EOF 'Wscript.Echo objRecordset.Fields("name") Call GetLastLogonTime(objRecordset.Fields("distinguishedName")) objRecordset.MoveNext Wend WScript.Echo "Total number of computers in domain: " & objRecordset.RecordCount WScript.Echo "Number of computers that have not logged on in " & intTimeLimit & " days: " & count objADODBConnection.Close '*********************** Sort Server List ****************************** WScript.Echo "Sorting..." Set DataList = CreateObject("ADOR.Recordset") DataList.Fields.Append "ComputerName", adVarChar, MaxCharacters DataList.Open Set objFSO = CreateObject("Scripting.FileSystemObject") Set objFile = objFSO.OpenTextFile("serverlist.txt", ForReading) Do Until objFile.AtEndOfStream strLine = objFile.ReadLine DataList.AddNew DataList("ComputerName") = strLine DataList.Update Loop objFile.Close DataList.Sort = "ComputerName" DataList.MoveFirst Do Until DataList.EOF strText = strText & DataList.Fields.Item("ComputerName") & vbCrLf DataList.MoveNext Loop Set objFile = objFSO.OpenTextFile("serverlist.txt", ForWriting) objFile.WriteLine strText objFile.Close WScript.Quit Function GetLastLogonTime(strComputerDN) On Error Resume Next Set objComputer = GetObject("LDAP://" & strDC & "/" & strComputerDN) 'WScript.Echo "Computer: " & objComputer.cn Set objLogon = objComputer.Get("lastLogonTimestamp") intLogonTime = objLogon.HighPart * (2^32) + objLogon.LowPart intLogonTime = intLogonTime / (60 * 10000000) intLogonTime = intLogonTime / 1440 'WScript.Echo "Approx last logon timestamp: " & intLogonTime + #1/1/1601# If intLogonTime + #1/1/1601# < Now - intTimeLimit Then strOld = "Over" & intTimeLimit & "-Y" count = count + 1 Else strOld = "Over" & intTimeLimit & "-N" End If 'Wscript.Echo objRecordset.Fields("dnsHostName") & "," & objRecordSet.Fields("operatingSystemVersion") _ ' & ",LOGON-" & intLogonTime + #1/1/1601# & "," & strOld objFile.WriteLine objRecordset.Fields("dnsHostName") & "," & objRecordSet.Fields("operatingSystemVersion") _ & "," & objRecordSet.Fields("operatingSystem") & ",LOGON-" & intLogonTime + #1/1/1601# & "," & strOld 'WScript.Echo " Has not logged on in " & intTimeLimit & " days" 'WScript.Echo " Approx last logon timestamp: " & intLogonTime + #1/1/1601# 'count = count + 1 'End If Set objComputer = Nothing End Function