Running Programs

Microsoft® Windows® 2000 Scripting Guide

One of the most important lessons to learn about scripting is this: Scripting is not the answer to all your system administration needs.

For one thing, scripting does not provide 100 percent coverage for all the administrative tasks that can be performed under Windows. For example, you can use scripts to create shared folders. But what if you want to set the offline folder options for that share? This procedure cannot be scripted using WSH or WMI. Instead, you must configure offline folder options using either the GUI or the Net.exe command.

For another, there is no reason to write a script if a tool already exists that fills your needs. Suppose you want to see the list of files that are stored in a folder on the local computer. You can spend the time creating a script to return this information. Alternatively, you can simply type dir at the command prompt and be done with it.

Using WSH scripts to help automate tasks does not require that you abandon the command-line tools or batch scripts that you currently use. If you have a batch script that performs well at a given task, there is no reason to create a WSH script that performs the same task.

On the other hand, you might want to augment the capabilities of a batch script with capabilities available only in the WSH scripting environment. For example, you might have a disk cleanup utility that you want to run only if free disk space falls below a specified level. It is possible to create a batch file that can determine free disk space and then decide whether to run the cleanup utility; however, the procedure for creating such a batch file is not particularly straightforward. By contrast, this same task can be accomplished quite easily in WSH: You can use the FileSystemObject or WMI to determine the free disk space and then either run or not run the disk cleanup utility.

One of the advantages of using WSH is that you do not have to choose WSH or choose batch files and command-line tools. The two approaches are not at odds with one another; instead, they complement one another. For example, you can use the WshShell Run and Exec methods in scripts to incorporate existing batch files or command-line tools.

Although running command-line tools and running batch scripts are important uses of the Run and Exec methods, these methods are not restricted to running a particular type of program. The Run and Exec methods enable your scripts to run any Windows program, including GUI applications. In addition, you can also run other scripts from within a script.

Comparing Run and Exec

The fact that there are two ways to run programs from a script leads to an obvious question: which method should you use in your scripts? The answer to that question depends on the script and what it needs to accomplish.

A script can use either the Run method or the Exec method to run a program in a manner similar to using the Run dialog box from the Start menu. Regardless of the method used, the program starts, and runs in a new process.

However, when you use the Run method, your script will not have access to the standard input, output, and error streams generated by the program being run. A script cannot use the Run method to run a command-line tool and retrieve its output.

For example, suppose you want to run Ping.exe and then examine the output to see whether the computer could be successfully contacted. This cannot be done using the Run command. Instead, you would need to ping the computer, save the results of the ping command to a text file, open the text file, read the results, and then parse those results to determine the success or failure of the command.

The following script uses the Run method to call Ping.exe, redirecting the output to a temporary file. The script opens and reads the text file, checks to see whether the command succeeded (by determining whether any of the lines of output begin with the word Reply), and then closes and deletes the temporary file:

Set objFSO = Wscript.CreateObject("Scripting.FileSystemObject")
Set objShell = Wscript.CreateObject("Wscript.Shell")
objName = objFSO.GetTempName
objTempFile = objName
objShell.Run "cmd /c ping -n 3 -w 1000 157.59.0.1 >" & objTempFile, 0, True
Set objTextFile = objFSO.OpenTextFile(objTempFile, 1)
Do While objTextFile.AtEndOfStream <> True
    strText = objTextFile.ReadLine
    If Instr(strText, "Reply") > 0 Then
        Wscript.Echo "Reply received."
        Exit Do
    End If
Loop
objTextFile.Close
objFSO.DeleteFile(objTempFile)

Although this approach works, it is somewhat complicated. If you need access to command-line output, you should use the Exec method instead. The following script also parses the output generated by Ping.exe. However, it does so by using the Exec method and by directly reading the output. There is no need to create, open, read, and delete a temporary file, and the script is only 9 lines long, compared with the 15 lines required to perform this same task using the Run method:

Set objShell = WScript.CreateObject("WScript.Shell")
Set objExecObject = objShell.Exec("cmd /c ping -n 3 -w 1000 157.59.0.1")
Do While Not objExecObject.StdOut.AtEndOfStream
    strText = objExecObject.StdOut.ReadLine()
    If Instr(strText, "Reply") > 0 Then
        Wscript.Echo "Reply received."
        Exit Do
    End If
Loop

In many respects, this makes the Exec method a better choice than the Run method. However, the Run method is still useful in a number of situations:

  • You might want to run the application in a specified window type, such as a minimized window. Exec offers no control over window style; Run offers the options listed in Table 3.9.

  • You might need to run a script on computers that do not have WSH 5.6 installed. Exec is supported only on WSH 5.6.

  • You might want to wait for the application being called to finish running before the script resumes. This can be done with either Run or Exec but requires less coding with Run.

Running Programs

The Run method accepts three parameters. The first and only required parameter is the name of the program you want to run. If the program is in the same folder as the script, or if it is located within the computer path, you need enter only the name (for example, Calc.exe). Otherwise, enter the full path to the program (C:\Admin\Monitoring\DiskSpace.exe).

The second parameter is an integer that indicates the window style with which the program should begin (assuming the program has a window). The window style determines such things as whether a window will be the active window or be maximized. Table 3.9 lists the integers that Run accepts as a second parameter as well as the corresponding the window styles.

Table 3.9 Integers Accepted by the Run Method for the Window Style

Integer

Window Style Description

0

Hides the window and activates another window.

1

Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time.

2

Activates the window and displays it as a minimized window.

3

Activates the window and displays it as a maximized window.

4

Displays a window in its most recent size and position. The active window remains active.

5

Activates the window and displays it in its current size and position.

6

Minimizes the specified window and activates the next top-level window in the Z order. The Z order is nothing more than the list detailing the order in which windows are to be activated. If you press ALT+TAB, you will see a graphical representation of the Z list.

7

Displays the window as a minimized window. The active window remains active.

8

Displays the window in its current state. The active window remains active.

9

Activates and displays the window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when restoring a minimized window.

10

Sets the show-state based on the state of the program that started the application.

For example, the script in Listing 3.15 starts Notepad. In line 1, the script sets the MAXIMIZE_WINDOW constant to 3, which represents an activated and maximized window style. In line 3, the script uses the WshShell Run method to start Notepad, passing it the MAXIMIZE_WINDOW constant so that the program runs in a maximized window.

Listing 3.15 Running a Program Using the Run Method

  
1
2
3
Const MAXIMIZE_WINDOW = 3
Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run "notepad.exe", MAXIMIZE_WINDOW

Note

  • Not all applications respond to the window style options. For example, Control Panel (Control.exe) always opens in the same way, regardless of the window style specified in the script.

The Run method also accepts a Boolean value as a third parameter that determines whether the script pauses until the called program is finished running or instead continues with the next command in the script. If this value is set to False (the default), the Run method simply issues the command to run the program but does not check to ensure that the program actually ran. If the third parameter is set to True, the script will wait for the program to finish running, return the integer exit code provided by the program, and then continue with the next line of the script.

If you set this value to False, you can run multiple programs at the same time; the script will start program A and then immediately start program B, even though program A is still running. This can enable your scripts to complete faster. However, it can also lead to possible problems: For example, what if program B cannot be run until program A has finished? If you are worried about possible "collisions" between programs, set this value to True. In that case, program B will not start until program A has concluded.

For example, this script runs Calculator and then waits until Calculator has been closed before proceeding. If Calculator is never closed, line 3 of this script will never execute:

Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run("calc.exe"),1,True
Wscript.Echo "Script completed."

Note

  • WSH keeps track of the specific instance of a program started using Run. For example, suppose you run the preceding script and then manually start a second instance of Calculator. If you close this second instance, the script will not respond. Instead, it will continue to wait until the initial instance of Calculator, the one started using Run, has been closed.

Running Command-Line Tools

Although both Run and Exec are well suited for running GUI programs from scripts, you are unlikely to call many GUI programs from within a script. After all, the basic idea behind most system administration scripts is to carry out a task without the need for any human intervention. Because GUI applications typically require human intervention, about the best you can do within a script is open the application; you are very limited in what you can do with the application after it has been opened.

This is not true for command-line tools, however. Most command-line tools are designed to run in automated fashion; after they have been started, there is no need for any human intervention. The tools start, perform their appointed task, and then terminate.

Both the Run method and the Exec method can be used to run command-line tools, although in either case you should use a slightly different syntax from the one used to run GUI tools. When you run a command-line tool using either of these methods, you should always preface the tool name with one of the following:

  • %comspec% /k

  • %comspec% /c

The %comspec% variable is an environment variable that specifies the command-line processor. By using %comspec%, you can create scripts that run on both Windows 98 computers (where the command-line processor is Command.exe) and on Windows 2000 computers (where the command-line processor is named Cmd.exe).

The %comspec% variable is not required; however, it does provide a way for a the command window in which a tool runs to remain on the screen. (By default, a command window opens, the tool runs, and then the command window closes as soon as the tool finishes. This means that you might not have time to view the output generated by that tool.)

Including %comspec% is also the only way to run command-line commands such as dir. This script will not run the dir command. Instead, you will receive an error message stating that dir could not be found. (This is because dir is not a stand-alone tool; there is, for example, no program named dir.exe.)

Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run("dir"), 1, True

However, this script, which first starts the command interpreter, will run the dir command:

Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run("%comspec% /K dir"), 1, True

The /k and /c parameters allow you to specify whether the command window will remain open after the script completes or whether it will be closed. If you want the window to remain open so that you can view the script output, use the /k parameter. If you want the window to close (as you might with a logon script), use the /c parameter.

For example, the following script runs the Cacls.exe tool, which, in this instance, displays permission settings for the folder C:\Scripts. The script leaves the command window open so that the results can be viewed:

Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run("%comspec% /K cacls.exe c:\scripts"), 1, True

By contrast, this script runs the Sc.exe tool and stops the Alerter service. As soon as the script completes, the command window closes:

Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run("%comspec% /c sc.exe stop alerter"), 1, True

Using Spaces in Command-Line Parameters

If a parameter passed to a command-line tool includes a space, that parameter must be enclosed in quotation marks. For example, to use Sc.exe to determine the keyname for the Upload Manager service, you need to use the following syntax:

sc.exe getkeyname "Upload Manager"

To use this same command within a script, you must also include quotation marks around the parameter. However, this is not entirely straightforward. For example, you might try placing quotation marks around Upload Manager, like this:

Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run("%comspec% /k sc.exe getkeyname "Upload Manager""), 1, True

When you run this script, you do not get the keyname for Upload Manager. Instead, you get the error message shown in Figure 3.11.

Figure 3.11 Incorrectly Specifying the Run Parameter

sas_wsh_112s

At first, this error message might seem nonsensical; after all, it says that the script expected to see a right parenthesis, and your code has a right parenthesis. As it turns out, though, the problem lies not with the parentheses but with the quotation marks. WSH correctly sees the first set of quotation marks (the ones right before %comspec%) as marking the start of the command string being passed to the Run method. However, it sees the second set of quotation marks (the ones right before the word Upload) as marking the end of the command string. To WSH, this is the command you are trying to execute:

objShell.Run("%comspec% /k sc.exe getkeyname ""

Because the syntax is not correct (a right parenthesis is required immediately after the second set of quotation marks), the script fails.

Anytime you need to include quotation marks as part of the command string, you must use a pair of quotation marks. For example:

Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run("%comspec% /k sc.exe getkeyname ""Upload Manager"""), 1, True

In this script:

  1. A single set of quotation marks is used to begin the command string.

  2. A pair of quotation marks is used with Upload Manager. This will cause "Upload Manager" (with the surrounding quotation marks) to be included as part of a command string.

  3. A single set of quotation marks is used to end the command string. In this example, that results in three quotation marks appearing, one right after another.

Running a Program and Directly Accessing Its Output

To run a program and use its output, a script can use the WshShell Exec method. The WshShell Exec method returns a WshScriptExec object that provides access to the programs standard output, standard input, and standard error streams. Your scripts can retrieve the output that results from running a program by accessing the programs standard output stream (StdOut).

The script in Listing 3.16 runs the command-line tool, Ipconfig.exe, which retrieves information about the networking configuration of a computer, including the IP address currently assigned to that computer. The script captures the output of the tool and filters it line by line, displaying only lines that include the word Address.

Listing 3.16 Running an Application and Using Its Output

  
1
2
3
4
5
6
7
8
9
10
Set objShell = WScript.CreateObject("WScript.Shell")
Set objExecObject = objShell.Exec("%comspec% /c ipconfig.exe")
Do Until objExecObject.StdOut.AtEndOfStream
 strLine = objExecObject.StdOut.ReadLine()
 strIP = Instr(strLine,"Address")
 If strIP <> 0 Then
 Wscript.Echo strLine
 End If
Loop

In line 2 of Listing 3.16, the script uses the Exec method to run the Ipconfig.exe command-line tool. The output generated by Opconfig.exe will be stored in the object reference named objExecObject.

In line 4, the script sets up a loop that will continue until the end of the programs standard output stream is reached. The script checks for the end of the stream by using the AtEndOfStream property of the StdOut TextStream object.

In line 5, the script reads a line of the programs output and stores it in the strLine variable.

In line 6, the script uses the VBScript Instr function to determine whether the word Address is stored in strLine. If the word Address is found, the script displays the line using the Echo method on line 8.

When you run Ipconfig.exe, you receive output similar to this:

Windows IP Configuration
Ethernet adapter Local Area Connection 2:
        Connection-specific DNS Suffix . : fabrikam.com
        IP Address. . . . . . . . . . . . : 192.168.248.248
        Subnet Mask . . . . . . . . . . . : 255.255.252.0
        Default Gateway . . . . . . . . . : 192.168.248.1

When you run the preceding script, you receive output only for those lines that contain the word Address:

        IP Address. . . . . . . . . . . . : 192.168.248.248

This enables you to run a command-line tool, check its output, and then have your script proceed accordingly.