Help !! How to get a list of outdated workstation from a domain ?
Hi, I'm running 93 domain controller(all outside) and i need to clean out the AD on each domain. What i would like to do is:
- Get a list of devices in the OU "Computers"
- Create and write this list to an text file "computer.txt"
- Ping the host name from that list and write the result in the same text file (ie. destination host unreachable, ...) with a filter of 60 days
- Create OU "Outdated computers" and move the outdated computers to this OU
- Finally, send this text file by email whit the Domain name in the subject.
Like i say, i have 93 domains, so it's a real pain to do 1 custom script for each domain.
Hope someone can help me.. I'm very lost.. :)
Thanks a million for all the help
Answers (3)
To get you started, here's a *very* QAD scripot I knocked up some time ago to get the last logon time for all AD objects. Note that this includes users, too but you can obviously edit the script to query for just users or just machines.
Option Explicit
'On Error Resume Next
Const ADS_SCOPE_SUBTREE = 2
Const ADS_PROPERTY_UPDATE = 2
Const ADS_PROPERTY_APPEND = 3
Const ADS_PROPERTY_DELETE = 4
Const ADS_PAGE_SIZE = 100
Const ADS_TIMEOUT = 30
Const adUseClientBatch = 3 '// Obsolete, same as adUseClient
Const adUseNone = 1 '// Obsolete, no cursor service
Const adUseServer = 2 '// Default, use the cursor supplied by provider or database
Const adUseClient = 3 '// Use client-side cursor supplied by the local cursor library
Const adOpenStatic = 3 '// Use static cursor
Dim strExcludeOUlist
Dim dtmTestDate
Dim dtmLastLogonTimeStamp
'//------------------------------------------------------------------------------------------------------------//
'// Force use of CScript
'//------------------------------------------------------------------------------------------------------------//
Call ForceCScriptExecution(True)
dtmTestDate = #16/03/2012# '// This is the date against which we're going to test.
'// It needs to be in US format so 6/1/2011 is 1st June 2011
dtmTestDate = DateAdd("d", -75, Date())
strExcludeOUList = "Exchange" '// Exclude any account with an OU which includes this text
Set objShell = CreateObject("Wscript.Shell")
lngBiasKey = objShell.RegRead("HKLM\System\CurrentControlSet\Control\TimeZoneInformation\ActiveTimeBias")
If (UCase(TypeName(lngBiasKey)) = "LONG") Then
lngBias = lngBiasKey
ElseIf (UCase(TypeName(lngBiasKey)) = "VARIANT()") Then
lngBias = 0
For intIndex = 0 To UBound(lngBiasKey)
lngBias = lngBias + (lngBiasKey(intIndex) * 256^intIndex)
Next
End If
Set objShell = Nothing
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext")
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.CursorLocation = adUseClient
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection
With objCommand
.Properties("SearchScope") = ADS_SCOPE_SUBTREE
.Properties("Page Size") = ADS_PAGE_SIZE
.Properties("Timeout") = ADS_TIMEOUT
.Properties("Cache Results") = False
End With
strCommandText = ""
strCommandText = strCommandText & "<LDAP://" & strDNSDomain & ">"
strCommandText = strCommandText & ";"
strCommandText = strCommandText & "("
strCommandText = strCommandText & "|(samAccountType=805306368)(samAccountType=805306369)"
strCommandText = strCommandText & ")"
strCommandText = strCommandText & ";distinguishedName,sAMAccountName,Name,lastLogonTimeStamp;Subtree"
'// Comma-delimited list of attribute values to retrieve
strAttributes = "distinguishedName,lastLogonTimeStamp"
objCommand.CommandText = strCommandText
Set objRecordSet = objCommand.Execute
With objRecordSet
.MoveFirst
.Sort = "Name asc"
WScript.Echo "Total number: " & .RecordCount
Do Until .EOF
'// Retrieve attribute values for the user
'strDN = .Fields("distinguishedName").Value
'// Convert Integer8 value to date/time in current time zone
On Error Resume Next
dtmLastLogonTimeStamp = ConvertInteger8ToDate(.Fields("lastLogonTimeStamp").Value, lngBias)
strName = .Fields("Name").Value
strsAMAccountName = .Fields("sAMAccountName").Value
strdistinguishedName = .Fields("distinguishedName").Value
'// The date needs to be in US format
If (dtmLastLogonTimeStamp < dtmTestDate) Then
'Wscript.Echo strName
'Wscript.Echo strsAMAccountName
If InStr(strdistinguishedName, strExcludeOUList) = 0 Then
Wscript.Echo strsAMAccountName & "|" & strdistinguishedName & "|" & dtmLastLogonTimeStamp
End If
Else
'Wscript.Echo strDN & ";" & dtmLastLogonTimeStamp
End If
.MoveNext
Loop
End With
Function ConvertInteger8ToDate(ByVal objDate, ByVal lngBias)
'// Function to convert Integer8 (64-bit) value to a date,
'// adjusted for local time zone bias
Dim lngAdjust
Dim lngDate
Dim lngHigh
Dim lngLow
lngAdjust = lngBias
lngHigh = objDate.HighPart
lngLow = objDate.LowPart
'// Account for bug in IADslargeInteger property methods
If (lngLow < 0) Then
lngHigh = lngHigh + 1
End If
If (lngHigh = 0) And (lngLow = 0) Then
lngAdjust = 0
End If
lngDate = #1/1/1601# + (((lngHigh * (2 ^ 32)) + lngLow) / 600000000 - lngAdjust) / 1440
ConvertInteger8ToDate = CDate(lngDate)
End Function
Sub ForceCScriptExecution(ByVal blnQuoteArguments)
Dim objShellRun
Dim strArgument
Dim strArguments
Dim strCmdLine
Dim intIndex
'// If running in CScript, do nothing
If UCase(Right(WScript.FullName, 11)) = "CSCRIPT.EXE" Then
Exit Sub
End If
If WScript.Arguments.Count > 0 Then
strArguments = ""
For intIndex = 0 To (WScript.Arguments.Count - 1)
If Len(strArguments) = 0 Then
strArguments = WScript.Arguments(intIndex)
Else
strArguments = strArguments & " " & WScript.Arguments(intIndex)
End If
Next
If blnQuoteArguments Then
strArguments = Chr(34) & strArguments & Chr(34)
End If
End If
'// If running in WScript, execute the script using CScript
'// and then quit this script
If UCase(Right(WScript.FullName, 11)) = "WSCRIPT.EXE" Then
Set objShellRun = CreateObject("WScript.Shell")
'objShellRun.Run "CSCRIPT.EXE """ & WScript.ScriptFullName & """", 1, False
strCmdLine = "CSCRIPT.EXE "
If InStr(WScript.ScriptFullName, " ") > 0 Then
strCmdLine = strCmdLine & Chr(34)
End If
strCmdLine = strCmdLine & WScript.ScriptFullName
If InStr(WScript.ScriptFullName, " ") > 0 Then
strCmdLine = strCmdLine & Chr(34)
End If
If Len(strArguments) > 0 Then
strCmdLine = strCmdLine & " "
strCmdLine = strCmdLine & strArguments
End If
objShellRun.Run strCmdLine, 1, False
Set objShellRun = Nothing
WScript.Quit
End If
'// If script engine is anything else, quit with an error
WScript.Echo "Unknown scripting engine."
WScript.Quit
End Sub
You may be able to leverage the dsquery command to your advantage in this case. I use it when cleaning AD computers but you have a much larger task you are trying to automate.
http://www.windowsnetworking.com/kbase/WindowsTips/Windows2003/AdminTips/Admin/PruningOldComputerAccountsinAD.html
As an example, the following command will find all computers in Active Directory that have not been logged into during the past 8 weeks:
dsquery computer -inactive 8 -limit 0