Looking for Critics

Anything VBScript-related, including Windows Script Host, WMI, ADSI, and more.
Forum rules
Do not post any licensing information in this forum.

Any code longer than three lines should be added as code using the 'Select Code' dropdown menu or attached as a file.
Locked
User avatar
colmtourque
Posts: 3
Joined: Tue Nov 06, 2007 6:58 am

Looking for Critics

Post by colmtourque » Tue Nov 06, 2007 7:06 am

I've written a script to do some server monitoring and I'm looking for critics to tell me the good the bad and the ugly. Anyone who desire please feel free.
The script searches ad for servers and then does some checks against the found servers looking for services, process usage, memory usage and drive space. If nothing else please feel free to use it and enjoy.
I have made use of some major resources online but sorry I do not cite them (to many and started deleting stuff as I was editing and lost track of who, what, when and where if you recoqnize code feel free to say so). But due to the massive borrowing I wanted to be sure and give back.

Thanks and enjoy:

'On Error Resume Next
'this value decides what is happening, what functions to call and such
'vParam = the systems to check to run
set vParam=wscript.arguments
Set WSHShell = CreateObject("WScript.Shell")
'load the paramater to a function
'vFunctionCall = Specify the Function
'vSystemCheck = 'logical disk' then check the processor
'vParam 1 and 2 load to ldapQuery
vFunctionCall = vParam(0)
'vOption = vParam(1)
'vOption = vParam(2)
'Variables for system info
Dim objWMIService, objItem, colItems, strComputer, vDiskInfoMessage
'Variables for LDAP info
Dim adoCommand, adoConnection, strBase, strFilter, strAttributes
Dim objRootDSE, strDNSDomain, strQuery, adoRecordset, strDN, objComputer
'array variables
Dim aSystems()
'Constants
Dim TIMETOPING, TIMETOCHECK
TIMETOPING=20
TIMETOCHECK=60
'This is the actual meat of the program
searchItem = "cn"
systemType = "Windows Server 2003"
'Loop through all servers on network
For each item in adSearch (searchItem, systemType)
item=trim(item)
'try to ping them
Set objShell = CreateObject("WScript.Shell")
Set objExec = objShell.Exec("cmd /c ping -n "& TIMETOPING &" -w 1000 " & item)
vPingResults = LCase(objExec.StdOut.ReadAll)
'if found now check stats and send messages on troubled systems
If (InStr(vPingResults, "reply from")) then
if not isNull(item) and item <> " " then
Select Case vFunctionCall
Case "checkDiskSpace"
checkDiskSpace(item)
Case "checkProcessors"
vProcResult = checkProcessors(item, 60)
if (vProcResult = true) then
vProcResult = 0
vProcResult item, 120
if (vProcResult = true) then
subj="Heavy Proc Utilization: " & item
mesg = " "
SendMessage subj, msg
end if
end if
Case "checkMemory"
vMemResult = checkMemory(item, 60)
if (vMemResult = true) then
vMemResult = 0
vMemResult item, 120
if (vMemResult = true) then
subj="Heavy Memory Utilization: " & item
mesg = " "
SendMessage subj, msg
end if
end if
Case "serviceInfo"
serviceInfo(item)
Case "eventlogSecurity"
eventlogSecurity(item)
End Select
end if
'system not found alert people
Else
if (not isNull(item) and item <> "") then
vSubjNotFound = "Unreachable Host: " & item
vBodyNotFound = "Unable to ping " & item
'SendMessage vSubjNotFound, vBodyNotFound
end if
End If
Next
'Functions
'This function send the message
Function SendMessage(vSubject, vMessage)
vMessage=Trim(vMessage)
if (vMessage="") then
msgBox "blank"
elseif (isNull(vMessage)) then
msgBox "null"
elseif (isEmpty(vMessage)) then
msgBox "Empty"
Else
Set objMessage = CreateObject("CDO.Message")
objMessage.Subject = vSubject
objMessage.From = "helpdesk@alcomgt.com"
objMessage.To = "kkrog1@alcomgt.com"
objMessage.TextBody = vMessage
'==This section provides the configuration information for the remote SMTP server.
'==Normally you will only change the server name or IP.
objMessage.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/config ... /sendusing") = 2
'Name or IP of Remote SMTP Server
objMessage.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/config ... smtpserver") = "mail.alcomgt.com"
'Server port (typically 25)
objMessage.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/config ... serverport") = 25
objMessage.Configuration.Fields.Update
'==End remote SMTP server configuration section==
objMessage.Send
End If
End Function
'Function to convert date format to WMI/SQL compliant
Function FunctionToday(dateVal, delimiter)
Dim dateMonth, dateDay
dateVal = CDate(dateVal)
delimiter = CStr(delimiter)
dateMonth = Month(dateVal)
dateDay = Day(dateVal)
FunctionToday = CStr(Year(dateVal)) & delimiter
If dateMonth < 10 Then
FunctionToday = FunctionToday & "0"
End If
FunctionToday = FunctionToday & CStr(dateMonth) & delimiter
If dateDay < 10 Then
FunctionToday = FunctionToday & "0"
End If
FunctionToday = FunctionToday & CStr(dateDay)
End Function
'This function searches AD for a Search Field of Search Type
Function adSearch(searchField, searchType)
' Setup ADO objects.
Set adoCommand = CreateObject("ADODB.Command")
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"
adoCommand.ActiveConnection = adoConnection
' Search entire Active Directory domain.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False
'query
adoCommand.CommandText = "SELECT " & searchField & " FROM 'LDAP://dc=domain,dc=alcomgt,dc=com' WHERE objectCategory='computer' AND operatingSystem='"& searchType &"'"
'Run the query.
Set adoRecordset = adoCommand.Execute
b=0
ReDim aSystems(0)
Do Until adoRecordset.EOF
aSystems(b) = adoRecordset.Fields(searchField).Value
'return aSystems(b)
adoRecordset.MoveNext
b=b+1
if b > 0 Then
'arraySize = UBound(aSystems) + 1
ReDim Preserve aSystems(UBound(aSystems) + 1)
end if
Loop
adSearch = aSystems
End Function
'Function to get total disk space
Function checkDiskSpace(vSystem)
Set objWMIService = GetObject _
("winmgmts:" & vSystem & "rootcimv2")
Set colItems = objWMIService.ExecQuery _
("Select * from Win32_LogicalDisk WHERE DriveType='3'")
'Get count of systems
b=0
For Each objCount in colItems
b=b+1
Next
'Apply count to array
Dim aDiskInfo(),aFreeSpace()
ReDim aFreeSpace(b),aDiskInfo(b)
a=0
'run through and place items into array
For Each objItem in colItems
'Division by 0 check
If (Int(objItem.Size) = 0) Then
aFreeSpace(a)=0
Else
aFreeSpace(a) = (Int(objItem.FreeSpace)/Int(objItem.Size))*100
aDiskInfo(a) = "Computer: " & objItem.SystemName & VbCr & _
" ==================================" & VbCr & _
"Drive Letter: " & objItem.Name & vbCr & _
"Description: " & objItem.Description & vbCr & _
"Volume Name: " & objItem.VolumeName & vbCr & _
"VolumeSerialNumber: " & objItem.VolumeSerialNumber & vbCr & _
"Size: " & objItem.Size & vbCr & _
"Free Space: " & objItem.FreeSpace & vbCr & _
"Percent Free Space: " & aFreeSpace(a) & "%" & vbCr & _
"Quotas Disabled: " & objItem.QuotasDisabled & vbCr & _
"Supports DiskQuotas: " & objItem.SupportsDiskQuotas & vbCr & _
"Supports FileBasedCompression: " & _
objItem.SupportsFileBasedCompression & vbCr & _
"Compressed: " & objItem.Compressed & vbCr & _
""
a=a+1
End If
Next
'Disk Free Space Message
vDiskInfoMessage = "NEW Alert Disk Free Space: " & vSystem
'send the message ensure that your sending all drives
for i=0 to a
if aFreeSpace(i) > 0 and aFreeSpace(i) < 5 then
SendMessage vDiskInfoMessage, aDiskInfo(i)
end if
next
checkDiskSpace = join(aDiskInfo)
End Function
'Function to check processor usage note that it takes an average over vTime
Function checkProcessors(vSystem, vTime)
Set objWMIService = GetObject _
("winmgmts:" & vSystem & "rootcimv2")
Set colPItems = objWMIService.ExecQuery _
("Select * from Win32_Processor")
'This loop Will run a few times
b=0
For Each objItem in colPITems
b=b+1
Next
Dim aTotalProcInfo()
Dim aAvgProcInfo()
ReDim aTotalProcInfo(b)
ReDim aAvgProcInfo(b)
vProcHeader = "Computer: " & vSystem & VbCr & _
" ==================================" & VbCr & _
"Process Load Percentage" & VbCr
'Get processors information over TIMETOCHECK Seconds

vSeconds = 0
do
a=0
For Each objItem in colPItems
aTotalProcInfo(a) = aTotalProcInfo(a) + objItem.LoadPercentage
a=a+1
Next
Wscript.sleep 1000
vSeconds = vSeconds + 1
loop until vSeconds = vTime
'Average it out
For c = 0 to UBound(aTotalProcInfo)
aAvgProcInfo(c) = aTotalProcInfo(c)/vTime
if (aAvgProcInfo(c) > 50) then
vFlag = "true"
end if
Next

checkProcessors = vFlag
End Function
Function checkMemory(vSystem, vTime)
Set objWMIService = GetObject _
("winmgmts:" & vSystem & "rootcimv2")
Set colMemory = objWMIService.ExecQuery _
("Select * from Win32_PerfRawData_PerfOS_Memory")
Set colTotalMemory = objWMIService.ExecQuery _
("Select * from Win32_ComputerSystem")
'Get total memory and convert to mb
For Each objItem in colTotalMemory
vCurrentMemory = objItem.TotalPhysicalMemory/1024/1024
Next
'now figure out if excessive usage is occuring
vUsedMemory = 0
vSeconds = 0
'check usage over 30 seconds
do
For Each objItem in colMemory
vUsedMemory = vUsedMemory + objItem.AvailableMBytes/vCurrentMemory
Next
Wscript.sleep 1000
vSeconds = vSeconds + 1
loop until vSeconds = vTime
If (vUsedMemory/vTime > 50) Then
vFlag = "true"
End If
checkMemory = vFlag
End Function
'Get all currently running services and report
Function serviceInfo(vSystem)
Set objWMIService = GetObject _
("winmgmts:" & vSystem & "rootcimv2")
Set colItems = objWMIService.ExecQuery _
("Select * from Win32_Service")
'Get count of systems
b=0
For Each objCount in colItems
b=b+1
Next
'Apply count to array
Dim aServiceName(),aServiceStartMode(),aServiceState(),aServiceInfo()
ReDim aServiceName(b),aServiceStartMode(b),aServiceState(b),aServiceInfo(b)
a=0
'run through and place items into array
For Each objItem in colItems
If (objItem.Name <> "HTTPFilter" and objItem.Name <> "Netman" and objItem.Name <> "Nla"_
and objItem.Name <> "NtLmSsp" and objItem.Name <> "RasMan" and objItem.Name <> "SNMP" _
and objItem.Name <> "Sysmon" and objItem.Name <> "TapiSrv" and objItem.Name <> "TermService" _
and objItem.Name <> "BITS" and objItem.Name <> "EUQ_Migrator" and objItem.Name <> "Server Administrator" _
and objItem.Name <> "dmadmin" and objItem.Name <> "Wmi" and objItem.Name <> "Ati HotKey Poller" _
and objItem.Name <> "ALG" and objItem.Name <> "SysmonLog" and objItem.Name <> "SNMPTRAP" _
and objItem.Name <> "AppMgmt" and objItem.Name <> "Altiris PXE Server" and objItem.Name <> "Altiris PXE MTFTP Server" _
and objItem.Name <> "SQLSERVERAGENT" and objItem.Name <> "WinHttpAutoProxySvc" and objItem.Name <> "swprv" _
and objItem.Name <>"VSS" and objItem.Name <>"VDS" and objItem.SystemName <> "BETASERVER") _
Then
aServiceStartMode(a) = objItem.StartMode
aServiceState(a) = objItem.State
If (aServiceStartMode(a) = "Disabled" and aServiceState(a) = "Running") Then
aServiceName(a) = objItem.Name
aServiceInfo(a)= "Service Disabled and Running: " & aServiceName(a) & " " & aServiceStartMode(a) & " " & VbCr
a=a+1
ElseIf (aServiceStartMode(a) = "Manual" and aServiceState(a) = "Running") Then
aServiceName(a) = objItem.Name
aServiceInfo(a)= "Service Manual and Running: " & aServiceName(a) & " " & aServiceStartMode(a) & " " & VbCr
a=a+1
ElseIf (aServiceStartMode(a) = "Auto" and aServiceState(a) <> "Running") Then
aServiceName(a) = objItem.Name
aServiceInfo(a)= "Service Automatic and Not Running: " & aServiceName(a) & " " & aServiceStartMode(a) & " " & VbCr
a=a+1
ElseIf (aServiceState(a) = "Paused") Then
aServiceName(a) = objItem.Name
aServiceInfo(a)= "Service Paused: " & aServiceName(a) & " " & aServiceStartMode(a) & " " & VbCr
a=a+1
else vFlag=False
End If
'a=a+1
End If
Next
'Loop through and only send messages if service was found
For c = 0 to a-1
If (inStr(aServiceInfo(c),"Service")) Then
vFlag = "true"
c=a
End If
Next
'Send the message this verifies that there really is a message
If (vFlag = "true") Then
vServiceSubject = "Services: " & vSystem
vServiceBody = Join(aServiceInfo)
SendMessage vServiceSubject, vServiceBody
End If
End Function
Function eventlogSecurity(vSystem)
vToday = FunctionToday(Date,"")
Set objWMIService = GetObject _
("winmgmts:" & vSystem & "rootcimv2")
Set colLoggedEvents = objWMIService.ExecQuery _
("Select * from Win32_NTLogEvent WHERE Type = 'Audit Failure' AND EventCode != '861' and TimeGenerated >='" & vToday & "'")
b=0
For Each objCount in colLoggedEvents
b=b+1
Next
Dim msg()
ReDim msg(b)
'Check to see if there is a real reason to send
If (b > 150) Then
For Each objEvent in colLoggedEvents
msg(a) = "Record No: " & a & VbCr & _
"Computer Name: " & objEvent.ComputerName & VbCr & _
"Event Code: " & objEvent.EventCode & VbCr & _
"Source Name: " & objEvent.SourceName & VbCr & _
"Event Type: " & objEvent.Type & VbCr & _
"User: " & objEvent.User & VbCr & _
"Time: " & objEvent.TimeGenerated & VbCr & _
"Message: " & objEvent.Message & VbCr & _
" "
a = a +1
Next
'Send the message
vSecuritySubject = "Security Log: " & vSystem & " " & b
vSecurityBody = Join(msg)
SendMessage vSecuritySubject, vSecurityBody
End If
End Function

User avatar
dm_4ever
Posts: 26
Joined: Fri Jul 06, 2007 6:59 am

Looking for Critics

Post by dm_4ever » Tue Nov 06, 2007 12:23 pm

It seems you have plenty of Sub/Functions which seems to be a rare thing, but definitely a good thing. However, I would take it further to eliminate any global variables with maybe a few constants as exceptions. If you are running this script on WinXP or better I would replace the ping test from using WSHShell to using WMI.Also, rather than connecting to WMI in each of your functions that gathers information I would connect once and pass the WMI object to the various function to gather the necessary information.

User avatar
colmtourque
Posts: 3
Joined: Tue Nov 06, 2007 6:58 am

Looking for Critics

Post by colmtourque » Tue Nov 13, 2007 6:33 am

Thanks for the insight. I did change to the wmi method (someone else had suggested).
Quick question, how would you go about passing the wmi functions. I was trying to figure that out and really could not get the logic down in my head.

The other thing I am ultimately gonna do is start logging this to an sql server and also keep a list of processes so that if anything odd pops up we can note it.

Sorry I did not reply back to soon, I was supposed to be notified of any replies but never was.

User avatar
jvierra
Posts: 13809
Joined: Tue May 22, 2007 9:57 am
Contact:

Looking for Critics

Post by jvierra » Tue Nov 13, 2007 7:21 am

dim oWMI
Set oWMI = Create....

Function GetWMIObject( oWMI, xxx, yyy )

set q = oWMI.ExecQuery( -- sdome query -- )
etc...
End FUnction

Locked