'==========================================================================
'File: ProcessWatchdog.vbs
'Version: 1.0
'Author: Bennett Scharf www.bennett-scharf.com
'Purpose: This script is used to terminate a hung process. You can configure
'
the process name, the maximum run time, notification options, And
'
logging options.
'
Note: This script is designed to loop continuoulsy. I was careful to ensure that
'
destructors were included in all the correct places to eliminate memory leaks.
'
Normally I trigger this via a Task Scheduler job that runs at startup.
'Creation Date: 25 May 2005
'Revision Date: n/a
'Related Files: cscript.exe -vbscript console command intrepreter part of standard OS install
'
ProcessWatchdog.reg - registry export file showing config parameters
'
VBSendMail.dll, a popular SMTP component for sending mail via an SMTP server
'Registry Settings See file ProcessWatchdog.reg Typical registry settings at the end of this file.
'
'Operating System: Windows 2000
'Usage: cscript ProcessWatchdog.vbs
'Exit codes: Normal exit: 0, Error Exit >0
'==========================================================================
Option Explicit
'Constants are generally stored here
'Configuration values are stored in the registry -- see ReadConfigVariable function
Const strProcName = "'SomeProcess.exe'" 'Process to be monitored be sure to enclose process name in single quotes!
Const strRegPath = "HKLM\Software\ScharfCo\Monitoring\"
While 1
CheckProcesses
WScript.Sleep(300000)
Wend
Sub CheckProcesses
'At present this is the main routine
Dim strComputer, intProcessAge, intMaxAge
Dim objWMIService, colProcessList, objProcess
intMaxAge = ReadConfigVariable("WatchdogMaxAge")
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colProcessList = objWMIService.ExecQuery _
("SELECT * FROM Win32_Process WHERE Name = " & strProcName)
For Each objProcess In colProcessList
intProcessAge = GetProcessAge(objProcess.CreationDate)
If intProcessAge > intMaxAge Then
LogProcessTermination objProcess.ProcessId, intProcessAge, UTCtoDate(objProcess.CreationDate)
AlertProcessTermination objProcess.ProcessId, intProcessAge, UTCtoDate(objProcess.CreationDate)
objProcess.terminate
End If
Next
Set objWMIService = Nothing
Set colProcessList = Nothing
Set objProcess = Nothing
End Sub
Function ReadConfigVariable(strVarName)
'Passed name of variable in registry path
'Returns variable contents from registry path
Dim WshShell
Set WshShell = Wscript.CreateObject("WScript.Shell")
ReadConfigVariable = WshShell.RegRead(strRegPath & strVarName)
Set WshShell = Nothing
End Function
Function GetProcessAge(datCreationDate)
'Passed creation date in WMI format
'Returns process age in minutes (in VB format)
Dim datVbCreationDate 'creation date in VB format
If Not IsNull(datCreationDate) Then
datVbCreationDate = UTCtoDate(datCreationDate)
GetProcessAge = DateDiff("n", datVbCreationDate, Now)
Else
GetProcessAge = 0
End If
End Function
Function UTCtoDate(UTCDate)
'Passed date in UTC format
'Returns date in VB format
UTCtoDate = CDate(Mid(UTCDate, 5, 2) & "/" & _
Mid(UTCDate, 7, 2) & "/" & _
Left(UTCDate, 4) & " " & _
Mid (UTCDate, 9, 2) & ":" & _
Mid(UTCDate, 11, 2) & ":" & _
Mid(UTCDate, 13, 2))
End Function
Sub LogProcessTermination(intProcessID, intProcessAge, datCreationDate)
'writes facts about process termination to a log file
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim strLogPath
Dim objLogFile
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
strLogPath = ReadConfigVariable("WatchdogLogPath")
If Not(fso.FileExists(strLogPath)) Then
'if the file doesn't exist, create it and write a hheader row
On Error Resume Next
Set objLogFile = fso.OpenTextFile(strLogPath, ForWriting, True)
If Err.Number <> 0 Then 'Trap file open errors and exit
Wscript.echo Err.Description
Wscript.quit (Err.Number)
End If
On Error GoTo 0
objLogfile.writeline "Time,PID,Age,Created"
objLogfile.Close
Set objLogfile = Nothing
End If
Set objLogFile = fso.OpenTextFile(strLogPath, ForAppending, True)
objLogFile.writeline Now & "," & intProcessID & "," & intProcessAge & "," & datCreationDate
objLogFile.Close
Set objLogFile = Nothing
Set fso = Nothing
End Sub
Sub AlertProcessTermination(intProcessId, intProcessAge, datCreationDate)
'Send alert via SMTP
Dim strRecipients, strSMTPHost, strSMTPFrom, strSMTPFromDisplayName
Dim objSendMail
strRecipients = ReadConfigVariable("WatchdogRecipients")
strSMTPHost = ReadConfigVariable("WatchdogSMTPHost")
strSMTPFrom = ReadConfigVariable("WatchdogSMTPFrom")
strSMTPFromDisplayName = ReadConfigVariable("WatchdogSMTPDisplayName")
Set objSendMail = CreateObject("vbSendMail.clsSendMail")
objSendMail.SMTPHost = strSMTPHost
objSendMail.From = strSMTPFrom
objSendMail.FromDisplayName = strSMTPFromDisplayName
objSendMail.Recipient = strRecipients
objSendMail.Subject = "Process Termination"
objSendMail.Message = "A Global Vision Server Process exceeded the maximum age and was terminated." & _
VbCrLf & "Server: " & GetServerName & _
VbCrlf & "Process ID: " & intProcessID & _
VbCrlf & "Process Age: " & intProcessAge/60 & " hours" & _
VbCrLf & "Process Creation Time: " & datCreationDate
objSendMail.Send
Set objSendMail = Nothing
End Sub
Function GetServerName
'Returns local server name
Dim WshShell, WshSysEnv
Set WshShell = WScript.CreateObject("WScript.Shell")
Set WshSysEnv = WshShell.Environment("PROCESS")
GetServerName = WshSysEnv("COMPUTERNAME")
Set WshShell = Nothing
Set WshSysEnv = Nothing
End Function
' Typical registry settings
'
' [HKEY_LOCAL_MACHINE\SOFTWARE\Scharfco\Monitoring]
' "WatchdogLogPath"="d:\\test.txt"
' "WatchdogMaxAge"=dword:0000001e
' "WatchdogRecipients"="bennett.scharf@test.net"
' "WatchdogSMTPHost"="mailexchanger.test.net"
' "WatchdogSMTPFrom"="notify@test.net"
' "WatchdogSMTPDisplayName"="GVI Process WatchDog"
'