Hack 5 Wait for and Optionally Terminate a Process

 < Day Day Up > 

Hack 5 Wait for and Optionally Terminate a Process

figs/expert.gif figs/hack05.gif

If you've wondered how to write code that waits for a process to finish before terminating it, here's the answer .

I have seen a number of discussions regarding the need for a VB script that waits for a process to finish. The script in this hack does this and more: it waits for a process to finish and optionally terminates the process if it has not finished within a specified amount of time.

This code is a modified form of what I use to control my software deployments, and it has two purposes. First, the code is designed to be certain that the deployment script waits until the initiated software setup executable is fully finished before proceeding. Even though the majority of recent software releases do not require this functionality when being deployed, it is still required for some legacy installations. Second, the code can perform a forceful termination of an application if this functionality is required.

This script accepts three arguments: the name of the executable to wait for or terminate, the amount of time to wait before terminating the specified executable, and (optionally) a switch specifying that the script should run silently. Note that the script uses Windows Management Instrumentation (WMI) for the process-management tasks , so make sure you're running the latest WMI version on your machine.

The Code

The script consists of several sections, which are described inline in the following sections.

Main routine

First, command-line switches are read in the main body area:

 Option Explicit ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' File:     vbsWaitForProcess.vbs ' Updated:  Nov 2002 ' Version:  1.0 ' Author:   Dan Thomson, myITforum.com columnist '           I can be contacted at dethomson@hotmail.com ' ' Usage:    The command processor version must be run using cscript '           cscript vbsWaitForProcess.vbs notepad.exe 60 S '           or '           The IE and Popup versions can be run with cscript or wscript '           wscript vbsWaitForProcess.vbs notepad.exe -1 ' ' Input:    Name of executable  (ex: notepad.exe) '           Time to wait in seconds before terminating the executable '               -1 waits indefinitely for the process to finish '               0 terminates the process imediately '               Any value > 0 will cause the script to wait the specified '               amount of time in seconds before terminating the process '           Silent mode  (S) ' ' Notes: ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' On Error Resume Next 'Define some variables Dim strProcess Dim intWaitTime Dim strSilent 'Get the command line arguments strProcess = Wscript.Arguments.Item(0) intWaitTime = CInt(Wscript.Arguments.Item(1)) strSilent = Wscript.Arguments.Item(2) Call WaitForProcess (strProcess, intWaitTime, strSilent) 
Check if process is running

Next, the ProcessIsRunning function determines if a process is running:

 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' Function: ProcessIsRunning ' ' Purpose:  Determine if a process is running ' ' Input:    Name of process ' ' Output:   True or False depending on if the process is running ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Function ProcessIsRunning( strProcess )     Dim colProcessList     Set colProcessList = Getobject("Winmgmts:").Execquery _         ("Select * from Win32_Process Where Name ='" & strProcess & "'")     If colProcessList.Count > 0 Then         ProcessIsRunning = True     Else         ProcessIsRunning = False     End If     Set colProcessList = Nothing End Function 
Terminate the process

In the next section, the ProcessTerminate function terminates a process:

 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' Function: TerminateProcess ' ' Purpose:  Terminates a process ' ' Input:      Name of process ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Function ProcessTerminate( strProcess )     Dim colProcessList, objProcess     Set colProcessList = GetObject("Winmgmts:").ExecQuery _         ("Select * from Win32_Process Where Name ='" & strProcess & "'")     For Each objProcess in colProcessList         objProcess.Terminate( )     Next     Set colProcessList = Nothing End Function 
Wait for process to terminate

Finally, in the WaitForProcess subroutine, the user interface is set up, the script waits while the process is active, and the process termination is initiated. I created three versions of the subroutine in an effort to demonstrate a few methods for displaying status messages. For example, here's how to display these messages using the command console:

 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' Sub: WaitForProcess ' ' Purpose:  Waits for a process ' ' Input:    Name of process '           Wait time in seconds before termination. '             -1 will cause the script to wait indefinitely '             0 terminates the process imediately '             Any value > 0 will cause the script to wait the specified '             amount of time in seconds before terminating the process '           Display mode. '             Passing S will run the script silent and not show any prompts ' ' Output:   On screen status ' ' Notes:    The version echos user messages in the command window via StdOut ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub WaitForProcess( strProcess, intWaitTime, strMode )   If ProcessIsRunning(strProcess) Then     Dim StdOut     Dim w : w = 0     Dim strPrompt     Dim intPause : intPause = 1     If UCase(strMode) <> "S" Then       strPrompt = "Waiting for " & strProcess & " to finish."       Set StdOut = WScript.StdOut       StdOut.WriteLine ""       StdOut.Write strPrompt     End If     'Loop while the process is running     Do While ProcessIsRunning(strProcess)       'Check to see if specified # of seconds have passed before terminating       'the process. If yes, then terminate the process       If w >= intWaitTime AND intWaitTime >= 0 Then         Call ProcessTerminate(strProcess)         Exit Do       End If       'If not running silent, post user messages       If UCase(strMode) <> "S" Then _         StdOut.Write "."       'Increment the seconds counter       w = w + intPause       'Pause       Wscript.Sleep(intPause * 1000)     Loop     If UCase(strMode) <> "S" Then       StdOut.WriteLine ""       Set StdOut = Nothing     End If   End If End Sub 

The result is shown in Figure 1-8.

Figure 1-8. Status message displayed in command console
figs/wsh_0108.gif

Alternatively, here's some code for displaying status messages in Internet Explorer:

 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' Sub: WaitForProcess ' ' Purpose:  Waits for a process ' ' Input:    Name of process '           Wait time in seconds before termination. '             -1 will cause the script to wait indefinitely '             0 terminates the process imediately '             Any value > 0 will cause the script to wait the specified '             amount of time in seconds before terminating the process '             Display mode. '             Passing S will run the script silent and not show any prompts ' ' Output:   On screen status ' ' Notes:    This version uses Internet Explorer for user messages ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub WaitForProcess( strProcess, intWaitTime, strMode )   If ProcessIsRunning(strProcess) Then     Dim objIntExplorer     Dim c : c = 0     Dim w : w = 0     Dim strPrompt     Dim intPause : intPause = 1     strPrompt = "Waiting for " & strProcess & " to finish."     'If not running silent, create reference to objIntExplorer     'This will be used for the user messages. Also set IE display attributes     If UCase(strMode) <> "S" Then       Set objIntExplorer = Wscript._       CreateObject("InternetExplorer.Application")       With objIntExplorer         .Navigate "about:blank"         .ToolBar = 0         .Menubar = 0         ' no menu         .StatusBar = 0         .Width=400         .Height = 80         .Left = 100         .Top = 100         .Document.Title = "WaitForProcess"       End With       'Wait for IE to finish       Do While (objIntExplorer.Busy)           Wscript.Sleep 200       Loop       'Show IE       objIntExplorer.Visible = 1     End If     Do While ProcessIsRunning(strProcess)       'Check to see if specified # of seconds have passed before terminating       'the process. If yes, then terminate the process       If w >= intWaitTime AND intWaitTime >= 0 Then         Call ProcessTerminate(strProcess)         Exit Do       End If       If UCase(strMode) <> "S" Then         objIntExplorer.Document.Body.InnerHTML = strPrompt & String(c, ".")         'Increment the counter.         'Reset the counter indicator if it's > 25 because         'we don't want it taking up a lot of screen space.         If c > 25 Then c = 1 Else c = c + 1         'Increment the seconds counter         w = w + intPause       End If       'Pause       Wscript.Sleep(intPause * 1000)     Loop     objIntExplorer.Quit( )             ' close Internet Explorer     Set objIntExplorer = Nothing      ' release object reference   End If End Sub 

The resulting status message is shown in Figure 1-9.

Figure 1-9. Displaying status messages in Internet Explorer
figs/wsh_0109.gif

Finally, here's code that uses the Popup method of Windows Scripting Host for displaying status messages:

 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' Sub: WaitForProcess ' ' Purpose:  Waits for a process ' ' Input:    Name of process '           Wait time in seconds before termination. '             -1 will cause the script to wait indefinitely '             0 terminates the process imediately '             Any value > 0 will cause the script to wait the specified '  '             amount of time in seconds before terminating the process '           Display mode. '             Passing S will run the script silent and not show any prompts ' ' Output:   On screen status ' ' Notes:    This version uses WshShell.Popup for user messages ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub WaitForProcess( strProcess, intWaitTime, strMode )   If ProcessIsRunning(strProcess) Then     Dim objWshShell     Dim c : c = 0     Dim w : w = 0     Dim strPrompt     Dim intPopupTimer : intPopupTimer = 2     Dim intPause : intPause = 1     strPrompt = "Waiting for " & strProcess & " to finish."     'If not running silent, create reference to objWshShell     'This will be used for the user messages     If UCase(strMode) <> "S" Then _       Set objWshShell = CreateObject("WScript.Shell")     'Loop while the process is running     Do While ProcessIsRunning(strProcess)       'Check to see if specified # of seconds have passed before terminating       'the process. If yes, then terminate the process       If w >= intWaitTime AND intWaitTime >= 0 Then         Call ProcessTerminate(strProcess)         Exit Do       End If       'If not running silent, post user prompt       If UCase(strMode) <> "S" Then         objWshShell.Popup strPrompt & String(c, "."), intPopupTimer, _         "WaitForProcess", 64         'Increment the counter.         'Reset the counter indicator if it's > 25 because         'we don't want it taking up a lot of screen space.         If c > 25 Then c = 1 Else c = c + 1       End If       'Increment the seconds counter       w = w + intPause + intPopupTimer       'Pause       Wscript.Sleep(intPause * 1000)     Loop     Set objWshShell = Nothing   End If End Sub 

The resulting dialog box is shown in Figure 1-10.

Figure 1-10. Displaying status messages in a dialog box
figs/wsh_0110.gif

Note that if you are assembling a standalone script, it should contain sections 1, 2, 3, and one option from section 4. If you would rather incorporate this code into your existing script, you need only sections 2, 3, and one option from section 4. You'll also need to add the call statement that is at the end of the main routine section. All the code sections are self-contained, which makes them easy to import into existing scripts.

Running the Hack

To use this hack, type the code into Notepad (with Word Wrap disabled) and save it with a .vbs extension as WaitForProcess.vbs . Or, if you don't want to tire your fingers out, download it from the O'Reilly web site instead.

Here are a few sample command-line examples. This will wait indefinitely until Notepad is closed:

 cscript WaitForProcess.vbs notepad.exe -1 

This will wait silently and indefinitely until Notepad is closed:

 cscript WaitForProcess.vbs notepad.exe -1 S 

And this will wait 10 seconds before Notepad is forcefully closed:

 cscript WaitForProcess.vbs notepad.exe 10 

Dan Thomson

 < Day Day Up > 


Windows Server Hacks
Windows Server Hacks
ISBN: 0596006470
EAN: 2147483647
Year: 2004
Pages: 163
Authors: Mitch Tulloch

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