Recipe6.13.Script: Process Doctor


Recipe 6.13. Script: Process Doctor

Have you ever wanted to know when a particular process terminates on a system? Perhaps an application is failing mysteriously and you find out about it only after a user complains. Or maybe you have an application that fails periodically and you want to start it up immediately after it fails. This is pretty easy to accomplish using both VBScript and the command line.

Using VBScript

With WMI and event handlers, process monitoring is straightforward. The following code monitors the calc.exe process, and as soon as it recognizes that it is no longer running, restarts it:

' ------ SCRIPT CONFIGURATION ------ strProcess = "calc.exe"  ' Image name of the process you want to monitor strComputer = "." ' ------ END CONFIGURATION --------- set objWMI = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") set colProcesses = objWMI.ExecNotificationQuery(_                       "select * from _ _instanceDeletionevent " _                     & " within 2 where TargetInstance isa 'Win32_Process' " _                    & " and TargetInstance.Name = '" & strProcess & "'") do     set objProcess = colProcesses.NextEvent    WScript.Echo "Process " & strProcess & _                 " (" & objProcess.TargetInstance.ProcessID & ") terminated"    intRC = objWMI.Get("Win32_Process").Create(strProcess, , , intProcessID)    if intRC = 0 Then       Wscript.Echo strProcess & " started. PID: " & intProcessID    else       Wscript.Echo strProcess & " did not start.  Error code: " & intRC    end if loop

The main method to note in this script is ExecNotificationQuery, which executes a WQL query and receives events that result from it. Let's break the query down. The select statement pulls all _ _instanceDeletionEvent objects:

"select * from _ _instanceDeletionEvent "

Anytime a process terminates, or a file is deleted, or a service is removed, that event is registered as a deletion event in WMI (_ _instanceDeletionEvent).[1] This is incredibly powerful. The select statement I used matches ALL deletion events, which isn't quite what we want. This is why the next statement is needed:

[1] Likewise, new instances of processes, files, services, etc., are captured as _ _instanceCreationEvent objects and anytime an instance is modified, it is registered as an _ _instanceModificationEvent.

" within 2 where TargetInstance isa 'Win32_Process' "

TargetInstance isa 'Win32_Process' filters out all deletion events except those of type Win32_Process. The within 2 statement informs WMI how often to check the system (in seconds) to see if anything new matches this query.

At this point, the query would match all terminating processes, so I restrict it to just the one we are interested in:

" and TargetInstance.Name = '" & strProcess & "'")

In the case of Win32_Process instanceDeletionEvent objects, the TargetInstance.Name property equals the name of the process. So here I set that equal to the strProcess variable, which contains calc.exe.

After I've called ExecNotificationQuery, I am ready to enter a loop to start retrieving events. I used a do loop, which makes this script run until you kill it. The first line in the do loop invokes the NextEvent method. This is a synchronous call that waits until an event occurs before the script continues. If the calc.exe process never dies, the script never moves beyond this step. If it does catch the process terminating, it prints out that process's PID and creates a new instance of the process.

Using a Command-Line Interface

You can do the exact same thing as the VBScript solution using a command line. Here is the complete command:

> for /L %v in (1,1,40) do (tasklist /FI "IMAGENAME eq calc.exe" /FO CSV /NH | findstr "calc.exe" || calc.exe)  & sleep 15

Let's break this long command line down. The first part is a for loop that starts at 1 and goes to 40 by 1 (i.e., 1, 2, 3, 4 . . . 40). The loop counter is placed in the %v variable.

for /L %v in (1,1,40)

Next is the command to execute within the loop. The first part of the command simply runs the tasklist.exe utility and performs a search for the calc.exe process. The last two options tell tasklist to print the results (/FO) in a comma-separated list (CSV) and not to print any headers (/NH).

do (tasklist /FI "IMAGENAME eq calc.exe" /FO CSV /NH

If calc.exe is running, this command would produce this output:

"calc.exe","4156","Console","0","2,804 K"

Whereas if it is not running, it would produce this:

INFO: No tasks running with the specified criteria.

The second part of the command pipes the output from tasklist to the findstr.exe utility:

| findstr "calc.exe"

I do this because we need a way to determine if calc.exe is running. All we really want is for tasklist to produce some output if it is running and not to generate anything if it isn't. So this findstr command helps out by removing the INFO: No tasks . . . . output if calc.exe isn't running.

Now, if the tasklist and findstr commands do not generate any output, the next command executes:

|| calc.exe)

If they generate output, this command won't execute, which is exactly what we want. It will run calc.exe only if calc.exe isn't running.

After we've done all this work to determine if calc.exe is running and to start it otherwise, we need to take a breather. Remember, this whole thing is in a for loop that will run 40 times. If we didn't put some sort of break in it, it would run 40 consecutive times without a pause. This is where the next command comes into play:

 & sleep 15

This pauses the whole command for 15 seconds. And since we are using a loop with 40 iterations, the whole command will run over a 10-minute period (15 40/60 = 10 minutes). If you want this monitor to run for longer, simply change the number of seconds after the sleep command or the number of iterations in the for loop.



Windows Server Cookbook
Windows Server Cookbook for Windows Server 2003 and Windows 2000
ISBN: 0596006330
EAN: 2147483647
Year: 2006
Pages: 380
Authors: Robbie Allen

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net