Please feel free to give this a shot.
Differences are -
accept all variables on the command line
test for connection before running "audit_windows"
non-connecting machines are logged to output_err_file with the intention of inputting this into OAv2 (will happen later).
varying debug levels - 0,1,2
can now audit a specific OU
[code]' the number of audits to run concurrently
number_of_audits = 10
debug_level = 1
' the name and path of the audit script to use
script_name = "c:\audit\audit_windows.vbs"
' set the below to your active directory domain
' format of LDAP://your.domain.org or LDAP://OU=group,DC=yourdomain,DC=org
local_domain = "LDAP://your.domain.org"
' if operating_system has a value,
' restricts the audit to only systems with the specified operating system
' leave blank for all computers, regardless of OS
operating_system = "Windows 2000 Professional"
operating_system = "Windows 2000 Server"
operating_system = "Windows XP"
operating_system = "Windows Server 2003"
operating_system = "Windows Vista"
operating_system = "Windows 7"
operating_system = "Windows Server 2008"
operating_system = "Server"
operating_system = ""
' if set, create an output file of all retrieved systems from active directory
output_file = ""
output_err_file = "error_pcs.txt"
' below we take any command line arguements
' to override the variables above, simply include them on the command line like submit_online=n
Set objArgs = WScript.Arguments
For Each strArg in objArgs
argName = left(strArg,inStr(strArg,"=")-1)
argValue = mid(strArg,inStr(strArg,"=")+1)
select case argName
case "output_file"
output_file = argValue
case "output_err_file"
output_err_file = argValue
case "operating_system"
operating_system = argValue
case "local_domain"
local_domain = argValue
case "script_name"
script_name = argValue
case "number_of_audits"
number_of_audits = int(argValue)
case "debug_level"
debug_level = int(argValue)
end select
Next
if (debug_level > 0) then
wscript.echo "Arguements and Variables"
wscript.echo "-------------------"
wscript.echo "Debug Level: " & debug_level
wscript.echo "Output File: " & output_file
wscript.echo "Output Error File: " & output_err_file
wscript.echo "Operating System: " & operating_system
wscript.echo "Domain: " & local_domain
wscript.echo "Audit Script Name: " & script_name
wscript.echo "Number of concurrent audits: " & number_of_audits
wscript.echo "-------------------"
end if
' leave the below settings
strComputer = "."
const HKEY_CLASSES_ROOT = &H80000000
const HKEY_CURRENT_USER = &H80000001
const HKEY_LOCAL_MACHINE = &H80000002
const HKEY_USERS = &H80000003
const FOR_APPENDING = 8
const ADS_SCOPE_SUBTREE = 2
Const adOpenStatic = 3
set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
set objWMIService2 = GetObject("winmgmts:\\" & strComputer & "\root\WMI")
set oReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")
set objShell = CreateObject("WScript.Shell")
set objFSO = CreateObject("Scripting.FileSystemObject")
set wshNetwork = WScript.CreateObject( "WScript.Network" )
set objlocalwmiservice = getobject("winmgmts:root\cimv2")
set colitems = objlocalwmiservice.execquery("select * from win32_process",,48)
for each objitem in colitems
if instr (objitem.commandline, wscript.scriptname) <> 0 then
current_pid = objitem.processid
end if
next
if (debug_level > 0) then
wscript.echo "Script Process ID: " & current_pid
wscript.echo "-------------------"
end if
Set adoCommand = CreateObject("ADODB.Command")
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"
Set adoCommand.ActiveConnection = adoConnection
' Search entire Active Directory domain.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")
strBase = "<" & local_domain & ">"
' Filter on user objects.
strFilter = "(&(objectCategory=computer))"
' Comma delimited list of attribute values to retrieve.
strAttributes = "name, adspath, operatingSystem, operatingSystemVersion, operatingsystemservicepack"
' Construct the LDAP syntax query.
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
if (debug_level > 1) then
wscript.echo "Ldap Query: " & strQuery
end if
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False
adoCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
Set adoRecordset = CreateObject("ADODB.Recordset")
Set adoRecordset.ActiveConnection = adoConnection
adoRecordset.Properties("Page Size") = 100
adoRecordset.Properties("Timeout") = 30
'adoRecordset.Properties("Cache Results") = False
adoRecordset.Properties("Searchscope") = ADS_SCOPE_SUBTREE
' Assign cursorType that allows forward and backward movement.
adoRecordset.cursorType = adOpenStatic
' Run the query.
adoRecordset.Source = strQuery
adoRecordset.Open
' Display number of records.
' This positions the cursor at the end of the recordset.
total_retrieved_computers = adoRecordset.RecordCount - 1
' Move the cursor back to the beginning.
' The cursorType assignment allows this.
adoRecordset.MoveFirst
redim pc_array(total_retrieved_computers) ' set array to computer count
redim err_array(5, total_retrieved_computers) ' set array to computer count
if (debug_level > 0) then
wscript.echo "-------------------"
wscript.echo "number of systems retrieved from ldap: " & total_retrieved_computers
wscript.echo "-------------------"
end if
all_count = 0
err_count = 0
if (debug_level > 0) then
wscript.echo "Testing systems for connectivity."
wscript.echo "-------------------"
end if
count = 0
Do Until adoRecordset.EOF
count = count + 1
system_name = adoRecordset.fields("name").value
computer_os = adoRecordset.fields("operatingSystem").value
if ( ((len(operating_system) >= 0) AND (instr(computer_os, operating_system) > 0)) AND (instr(system_name, "DPWQBELL") = 0) AND (instr(system_name, "DPWCTX") = 0) ) then
if (debug_level > 0) then
wscript.echo system_name & " - matches OS filter"
end if
if (not isempty(adoRecordset.fields("operatingSystem").value)) then
ad_operatingsystem = adoRecordset.fields("operatingSystem").value
else
ad_operatingsystem = ""
end if
if (not isempty(adoRecordset.fields("operatingSystemVersion").value)) then
ad_os_version = adoRecordset.fields("operatingSystemVersion").value
else
ad_os_version = ""
end if
if (not isempty(adoRecordset.fields("operatingsystemservicepack").value)) then
ad_servicepack = adoRecordset.fields("operatingsystemservicepack").value
else
ad_servicepack = ""
end if
if (not isempty(adoRecordset.fields("adspath").value)) then
ad_ou = Mid(adoRecordset.fields("adspath").value, InStr(adoRecordset.fields("adspath").value, ",")+1, len(adoRecordset.fields("adspath").value))
else
ad_ou = ""
end if
if (debug_level > 1) then
wscript.echo system_name
wscript.echo "Match On: " & operating_system
wscript.echo "OS: " & computer_os
wscript.echo "Formatted ADS Path: " & ad_ou
wscript.echo "ServicePack: " & ad_servicepack
wscript.echo "Version: " & ad_os_version
end if
strCommand = "%comspec% /c ping -n 3 -w 1000 " & system_name & ""
Set objExecObject = objShell.Exec(strCommand)
'clears echo replies left in strText from the previous loop
strText=""
Do While Not objExecObject.StdOut.AtEndOfStream
strText = objExecObject.StdOut.ReadAll()
If Instr(strText, "Reply") > 0 Then
If Err.Number > 0 then
' On, but returned an error.
err_count = err_count + 1
err_array(1, err_count) = system_name
err_array(2, err_count) = ad_operatingsystem
err_array(3, err_count) = ad_servicepack
err_array(4, err_count) = ad_ou
if (debug_level >0) then
wscript.echo space(len(system_name)) & " - cannot connect"
end if
else
' Available.
all_count = all_count + 1
pc_array(all_count) = system_name ' feed computers into array
if (debug_level >1) then
wscript.echo space(len(system_name)) & " - can connect"
end if
num_running = HowMany
while num_running > number_of_audits
wscript.echo("processes running (" & num_running & ") greater than number wanted (" & number_of_audits & ")")
wscript.echo("therefore - sleeping for 4 seconds.")
wscript.sleep 4000
num_running = HowMany
wend
command1 = "cscript //nologo " & script_name & " " & pc_array(i)
set sh1=wscript.createobject("wscript.shell")
sh1.run command1, 6, false
set sh1 = nothing
num_running = HowMany
end if
'flushes error code from the previous loop
Err.Clear
Else
' Unavailable.
err_count = err_count + 1
err_array(1,err_count) = system_name
err_array(2, err_count) = ad_operatingsystem
err_array(3, err_count) = ad_servicepack
err_array(4, err_count) = ad_ou
err_array(5, err_count) = ad_os_version
if (debug_level >0) then
wscript.echo space(len(system_name)) & " - cannot connect"
end if
End If
Loop
else
if (debug_level > 1) then
wscript.echo " " & system_name & " - does not match OS filter"
end if
end if
if (debug_level > 1) then
wscript.echo "-------------------"
end if
adoRecordset.MoveNext
loop
' Clean up.
adoRecordset.Close
adoConnection.Close
if (debug_level > 0) then
wscript.echo "-------------------"
wscript.echo "number of systems retrieved from ldap: " & total_retrieved_computers
wscript.echo "number of available matching systems: " & all_count
wscript.echo "number of uncontactable matching systems: " & err_count
wscript.echo "-------------------"
end if
redim Preserve pc_array(all_count)
redim Preserve err_array(5, err_count)
' generates a text file of retrieved PCs
if (output_file > "") then
for i = 0 to ubound(pc_array)
retrieved_from_ad = retrieved_from_ad & pc_array(i) & vbcrlf
next
set objTS = objFSO.OpenTextFile(output_file, FOR_APPENDING, True)
objTS.Write retrieved_from_ad
end if
if (ubound(err_array,2) > 0) then
' todo
' send the output of each line of err_array to an input page from OAv2
result = "<?xml version=""1.0"" encoding=""ISO-8859-1""?>" & vbcrlf
system_timestamp = Year(Now()) & "-" & Right("0" & Month(Now()),2) & "-" & Right("0" & Day(Now()),2) & " " & Right("0" & Hour(Now()),2) & ":" & Right("0" & Minute(Now()),2) & ":" & Right("0" & Second(Now()),2)
for i = 1 to ubound(err_array,2)
system_os_family = os_family(err_array(2,i))
system_os_icon = os_icon(err_array(2,i))
result = result & "<system>" & vbcrlf
result = result & " <sys>" & vbcrlf
result = result & " <system_timestamp>" & escape_xml(system_timestamp) & "</system_timestamp>" & vbcrlf
result = result & " <system_hostname>" & escape_xml(err_array(1,i)) & "</system_hostname>" & vbcrlf
result = result & " <system_domain>" & escape_xml(err_array(4,i)) & "</system_domain>" & vbcrlf
result = result & " <system_type>system</system_type>" & vbcrlf
result = result & " <system_os_icon>" & system_os_icon & "</system_os_icon>" & vbcrlf
result = result & " <system_os_group>Windows</system_os_group>" & vbcrlf
result = result & " <system_os_family>" & escape_xml(system_os_family) & "</system_os_family>" & vbcrlf
result = result & " <system_os_name>" & escape_xml(err_array(2,i)) & "</system_os_name>" & vbcrlf
result = result & " <system_os_version>" & escape_xml(err_array(5,i)) & "</system_os_version>" & vbcrlf
result = result & " </sys>" & vbcrlf
result = result & "</system>" & vbcrlf
next
' generates a text file of PCs that we cannot connect to
if (output_err_file > "") then
set objTS = objFSO.OpenTextFile(output_err_file, FOR_APPENDING, True)
objTS.Write result
end if
end if
' finish up
wscript.quit()
Function HowMany()
Dim Proc1,Proc2,Proc3
CheckForHungWMI()
Set Proc1 = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set Proc2 = Proc1.ExecQuery("select * from win32_process" )
HowMany=0
For Each Proc3 in Proc2
If LCase(Proc3.Caption) = "cscript.exe" Then
HowMany=HowMany + 1
End If
Next
End Function
Sub CheckForHungWMI()
' Get the current date in UTC format
Set dtmStart = CreateObject("WbemScripting.SWbemDateTime")
dtmStart.SetVarDate Now, True
' Subtract the script_timeout value
dtmNew = DateAdd("s", (script_timeout * -1), dtmStart.GetVarDate(True))
' Convert our dtmNew time back to UTC format, since that's the format needed for the WMIService query, below.
Set dtmTarget = CreateObject("WbemScripting.SWbemDateTime")
dtmTarget.SetVarDate dtmNew, True
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
' Pull a list of all processes that are over (script_timeout) seconds old
Set colProcesses = objWMIService.ExecQuery _
("Select * from Win32_Process WHERE CreationDate < '" & dtmTarget & "'")
For each objProcess in colProcesses
' Look for cscript.exe processes only
if objProcess.Name = "cscript.exe" then
' Look for audit.vbs processes with the //Nologo cmd line option.
' NOTE: The //Nologo cmd line option should NOT be used to start the initial audit, or it will kill itself off after script_timeout seconds
if InStr(objProcess.CommandLine, "//Nologo") and InStr(objProcess.CommandLine, "audit.vbs") then
' The command line looks something like this: "C:\WINDOWS\system32\cscript.exe" //Nologo audit.vbs S0259W11
' Get the position of audit.vbs in the command line, and add 10 to get to the start of the workstation name
position = InStr(objProcess.CommandLine, "audit.vbs") + 10
affectedComputer = Mid(objProcess.CommandLine,position)
Echo("" & Now & "," & affectedComputer & " - Hung Process Killed. ")
LogKilledAudit("Hung Process Killed for machine: " & affectedComputer)
objProcess.Terminate
end if
end if
Next
End Sub
Function LogKilledAudit(txt)
on error resume next
dim Today, YYYYmmdd, fp, txtarr, txtline, todaystr
today=Now
logfilename="killed_audits.log"
todaystr=datepart("yyyy", today)&"/"&_
right("00"&datepart("m", today), 2)&"/"&_
right("00"&datepart("d", today), 2)&" "&_
right("00"&datepart("h", today), 2)&":"&_
right("00"&datepart("n", today), 2)&":"&_
right("00"&datepart("s", today), 2)
Set objFSO = CreateObject("Scripting.FileSystemObject")
set fp=objFSO.OpenTextFile(logfilename, 8, true)
If err<>0 then wscript.echo err.number&" "&err.description
txtarr=Split(txt, vbcrlf)
txt=""
For each txtline in txtarr
txtline=trim(txtline)
if txtline<>"" then
txt=txt&todaystr&" - "&txtline&vbcrlf
End if
Next
WScript.Echo(left(txt, len(txt)-2))
fp.write txt
fp.Close
set fp=Nothing
LogKilledAudit=True
End Function
function os_family(os)
if InStr(os, " 95") then os_family="Windows 95"
if InStr(os, " 98") then os_family="Windows 98"
if InStr(os, " NT") then os_family="Windows NT"
if InStr(os, "2000") then os_family="Windows 2000"
if InStr(os, " XP") then os_family="Windows XP"
if InStr(os, "2003") then os_family="Windows 2003"
if InStr(os, "Vista") then os_family="Windows Vista"
if InStr(os, "2008") then os_family="Windows 2008"
if InStr(os, "Windows 7") then os_family="Windows 7"
end function
function os_icon(os)
if InStr(os, " 95") then os_icon="windows_old"
if InStr(os, " 98") then os_icon="windows_old"
if InStr(os, " NT") then os_icon="windows_old"
if InStr(os, "2000") then os_icon="windows_old"
if InStr(os, " XP") then os_icon="windows"
if InStr(os, "2003") then os_icon="windows"
if InStr(os, "Vista") then os_icon="windows"
if InStr(os, "2008") then os_icon="windows_new"
if InStr(os, "Windows 7") then os_icon="windows_new"
end function
function escape_xml(data)
if IsNull(data) then
escape_xml = ""
else
data = replace(data,"&","&")
data = replace(data,"<","<")
data = replace(data,">",">")
data = replace(data,"""",""")
data = replace(data,"'","'")
data = trim(data)
escape_xml = data
end if
end function[/code]