Share via


Working with Command-Line Arguments

Microsoft® Windows® 2000 Scripting Guide

Command-line arguments are values that you enter at the command line when you run a script. If you have worked with command-line tools, you are already familiar with the concept of arguments. For example, when you run Ping.exe, you must supply, at a minimum, the name or the Internet Protocol (IP) address of the computer being pinged as a command-line argument:

ping 192.168.1.1

Providing values to a script by means of the command line is convenient in cases in which you expect the values to be different each time the script runs. If the values were hard coded within the script, changing the values would require you to edit the script. Using command-line arguments saves time in these cases.

Again, this is no different from working with command-line tools. Ping.exe uses command-line arguments to provide flexibility: This way, you can attempt to ping any computer anywhere. If Ping.exe did not accept command-line arguments, you would either need a separate version of the program for each computer you wanted to ping, or you would have to edit and recompile the source code any time you wanted to ping a different computer.

Command-line arguments are stored in the WshArguments collection, which you access through the Arguments property of the WScript object as shown in Figure 3.8. In addition to storing all command-line arguments in the WshArguments collection, WSH automatically filters each argument into the WshNamed or WshUnnamed collection based on the format of the argument.

Figure 3.8 WSH Command-Line Argument Collections

guide_sas_wsh_60c

How Command-Line Arguments Are Stored and Filtered

When you run a script with command-line arguments, the WSH runtime stores these values in a location in memory represented by the WshArguments collection. The WSH runtime stores the arguments in the WshArguments collection in the order in which they were entered on the command line: WScript.Arguments.Item(0) contains the first command-line argument, WScript.Arguments.Item(1) contains the second argument, and so on.

In addition to storing all command-line arguments in the WshArguments collection, WSH automatically filters the command-line arguments into one of two subcollections: WshNamed or WshUnnamed. Arguments that conform to /name:value format are stored in the WshNamed collection, and arguments that do not follow the /name:value format are stored in the WshUnnamed collection. The purpose behind filtering arguments will become clear later in this section.

For example, the following command runs the ServerStats.vbs script and passes three command-line arguments to the script: /s:atl-dc-01, /u:admin, and perf.

cscript serverstats.vbs  /s:atl-dc-01  /u:admin  perf

The command-line arguments follow the script name and are separated by one or more spaces. Because of this, command-line arguments that contain white space must be enclosed in quotation marks to be treated as a single argument. For example, in this command, the third argument contains a blank space. As a result, the entire argument must be enclosed in quotation marks:

cscript serverstats.vbs  /s:atl-dc-01  /u:admin  "perf monitor"

Without the quotation marks, perf and monitor would be treated as separate arguments.

Figure 3.9 illustrates the contents of the three argument collections having run status.vbs with the three command-line arguments /s:atl-dc-01, /u:admin, and perf.

Figure 3.9 Mechanics of the WSH Argument Collections

sas_wsh_105c

All command-line arguments are stored in the WshArguments collection exactly as they are typed on the command line. Count and Length return the total number of command-line arguments entered on the command line.

The WshNamed filtered collection contains the two named arguments. Named arguments are arguments that consist of two parts: a name and a value. The name must be prefaced with a forward slash, and a colon must separate the name from the value. The slash prefix and the colon separator are fixed and cannot be changed. For example, you cannot use a hyphen in place of the slash; the following command will not pass Server as a named argument; instead, it will treat -Server:atl-dc-01 as the value of a single unnamed argument:

cscript  serverstats.vbs  -Server:atl-dc-01

If you examine Figure 3.9 closely, you will see that named arguments are modified before they are stored in the WshNamed collection. The name portion of the argument becomes the index, or key, and is used with the WshNamed Item property to identify the argument to retrieve. The name is also used with the WshNamed Exists method to check whether a named argument was provided to the script at run time. The slash prefix and the colon separator are discarded, and only the value portion of the named argument is stored in the Item property of the WshNamed collection. Like WshArguments, the WshNamed Count method and Length property return the number of filtered arguments in the WshNamed collection.

The WshUnnamed filtered collection contains the one unnamed argument: perf. The WshUnnamed Count method and Length property return the number of filtered arguments in the WshUnnamed collection.

There are three ways to access command-line arguments:

  • You can access the entire set of arguments using the WshArguments collection.

  • You can access the arguments that have names using the WshNamed collection.

  • You can access the arguments that have no names using the WshUnnamed collection.

Using the Default Arguments Collection

As described in the preceding topic, all command-line arguments are stored in the default arguments collection, WshArguments. The WshArguments collection is accessed through the WScript Arguments property. WshArguments provides two methods and four properties to read and work with command-line arguments.

Methods

Count. Returns the total number of arguments in the WshArguments collection.

ShowUsage. Echoes usage instructions about the script. This is constructed from information provided in the <runtime> section of a Windows Script File (.wsf). Windows Script Files are not discussed in this book.

Properties

Named. Provides access to the WshNamed collection. WshNamed is a filtered collection of arguments, where each argument conforms to the following format: /name:value. Command-line arguments that conform to the /name:value format are called named arguments in WSH.

Unnamed. Provides access to the WshUnnamed collection. WshUnnamed is a filtered collection of arguments, drawn from WshArguments, that do not conform to the /name:value format. Windows Script Host refers to these as unnamed arguments.

Length. Returns the total number of arguments in the WshArguments collection.

Note

  • You might have noticed that the Length property is identical to the Count method. Length was provided to maintain a level of consistency with the ECMAScript Language Specification, Standard ECMA-262, which JScript is based on. Although either Count or Length can be used to determine the number of arguments passed to VBScript, you must use Length with JScript. Any attempt to use Count with JScript will result in a run-time error.

Item(n). Retrieves the element from the WshArguments collection that corresponds to the index number enclosed in parentheses.

The following command runs a fictitious script named GetEvents.vbs with three arguments:

cscript getevents.vbs atl-dc-01 "Directory Service" 1130

WSH stores the three arguments in the WshArguments collection in the order in which they were entered, and exactly as they were typed on the command line. To read the three arguments, you use the WScript Arguments property in combination with the WshArguments Item property as shown here:

ServerName = WScript.Arguments.Item(0)
EventLog = WScript.Arguments.Item(1)
EventID = WScript.Arguments.Item(2)

Because collections are zero-based, WScript.Arguments.Item(0) points to the first argument in the WshArguments collection. WScript.Arguments.Item(1) points to the second argument, which is enclosed inside quotation marks because the argument, Directory Services, contains a space. Omitting the quotation marks would cause the two words to be treated as separate arguments, which would lead to errors because incorrect values would be assigned to the EventLog and EventID variables. WScript.Arguments.Item(2) points to the third argument.

The collection looks like the one shown in Table 3.6.

Table 3.6 Sample WSH Arguments Collection

Item

Value

0

atl-dc-01

1

Directory Service

2

1130

If the fictitious script employed additional arguments, WScript.Arguments.Item(3) would point to the fourth argument, WScript.Arguments.Item(4) would point to the fifth argument, and so on.

There is no fixed limit on the number of arguments that can be stored in the WshArguments collection. However, the entire command line, which includes the host name, host options, script name, and script arguments, cannot exceed the maximum command-line length. Exceeding the maximum command-line length generally is not a problem unless you use the WSH Drag and Drop feature to populate WshArguments. The maximum command-line length also applies to WSH Drag and Drop.

You can reduce the amount of typing necessary to access each argument by setting a reference to the WshArguments collection by way of the WScript Arguments property. Use the VBScript Set keyword followed by the variable name you want to use to access the WshArguments collection. Set is required because collections are standard COM objects. The following example is functionally equivalent to the preceding example despite some syntactical differences.

Set args = WScript.Arguments
ServerName = args.Item(0)
EventLog = args.Item(1)
EventID = args.Item(2)

The previous three examples assume GetEvents.vbs is always passed three command-line arguments. While omitting any kind of argument verification might be OK for a quick ad hoc script, failing to perform some level of verification can lead to error-prone scripts, especially when the script is shared with other users.

The following command runs the fictitious GetEvents.vbs script without any arguments.

cscript getevents.vbs

Running GetEvents.vbs without arguments using one of the three previous examples would result in the following run-time error:

C:\Scripts\GetEvents.vbs(2, 1) Microsoft VBScript runtime error: Subscript out of range

Any attempt at using the Item property to access an argument that does not exist will result in a Subscript out of range run-time error. Listing 3.6 demonstrates how to use the WshArguments Count method to verify that the correct number of command-line arguments is provided to the script at run time.

Listing 3.6 Using Count to Verify the Number of Arguments Used

  
1
2
3
4
5
6
7
8
If WScript.Arguments.Count = 3 Then
 ServerName = WScript.Arguments.Item(0)
 EventLog = WScript.Arguments.Item(1)
 EventID = WScript.Arguments.Item(2)
Else
 Wscript.Echo "Usage: GetEvents.vbs ServerName EventLog EventID"
 Wscript.Quit
End If

In Line 1 of Listing 3.6, the script uses the WshArguments Count method to obtain the number of command-line arguments in the WshArguments collection. If the value is equal to 3, the script initializes the ServerName, EventLog, and EventID variables with the three arguments in the WshArguments collection. Otherwise, the script echoes usage instructions and immediately exits.

Unnamed Command-Line Arguments

Unnamed arguments are entered on the command line as values only, without an associated name. At times the order of your arguments might be irrelevant; for example, a script might require you to type in three computer names, and it makes no difference which computer the script runs against first. Otherwise, unnamed arguments must be entered in the order that the script requires.

You might want to use unnamed arguments when your script:

  • Accepts only one or two command-line arguments. If your script accepts only the name of a folder as its sole command-line argument, there is no reason to make this a named argument.

  • Accepts arguments that are all of the same type and are each used in the same way within your script. For example, you might have a script that backs up and clears event logs on all computers whose names are entered as command-line arguments. Because all the arguments are the same (names of servers), and because the order is probably irrelevant, there is no reason to use named arguments.

When you run a script with unnamed command-line arguments, the WSH runtime stores the arguments in the WshArguments collection in the order in which they were entered on the command line. The arguments can then be referenced in the script using index numbers that represent the order in which they were entered. The sequence of index numbers begins with 0.

The script in Listing 3.7 uses the unnamed command-line arguments collection to retrieve and display the command-line arguments provided to it.

Listing 3.7 Retrieving Command-Line Arguments Using the Arguments Collection

  
1
2
3
4
5
6
7
strServer = WScript.Arguments.Item(0)
strPacketSize = WScript.Arguments.Item(1)
strTimeout = WScript.Arguments.Item(2)
Wscript.Echo "Pinging Server: " & strServer
Wscript.Echo "Packet Size: " & strPacketSize
Wscript.Echo "Timeout: " & strTimeout

The following command runs the script with the command-line arguments entered in the order required by the script.

EchoUnnamedArgs.vbs DCServer01 100 5000

This command produces the following output:

Pinging Server: DCServer01
Packet Size: 100
Timeout: 5000

This command runs the same script with the command-line arguments entered in the wrong order.

EchoUnnamedArgs.vbs 100 DCServer01 5000

This command produces the following output:

Pinging Server: 100
Packet Size: DCServer01
Timeout: 5000

The output from the first command is correct but the output from the second command is incorrect. Because the script is written using unnamed arguments, the order in which the command-line arguments are entered is crucial for the script to work properly. If the script actually tried to run Ping.exe, the procedure would fail because there is no server named 100 and no such thing as a packet size of DCServer01.

Named Command-Line Arguments

As the preceding example showed, the order in which unnamed arguments are entered can make the difference between a script that runs successfully and a script that does not. This places a considerable burden on administrators running the script; not only must they supply the correct arguments, but they must also supply them in the correct order. One mistake will likely cause the script to fail.

To make it easier for people to run scripts that use multiple arguments, you can use named arguments instead. Named arguments are entered on the command line as values with associated names. They can be entered in any order.

A named argument begins with a slash (/), and the name and the value are separated by a colon (:). The following command runs a script named ServerTest.vbs with two named arguments:

ServerTest.vbs /Server:HRServer01 /Timeout:3000

The name of the first argument is Server, and its value is HRServer01. The name of the second argument is Timeout, and its value is 3000. These arguments could also be entered in the reverse order, as follows:

ServerTest.vbs /Timeout:3000 /Server:HRServer01

When you run a script with named command-line arguments, each arguments name and value are stored in the WshNamed collection.

The script in Listing 3.8 uses the named command-line arguments collection to retrieve and display the command-line arguments it receives in the command window.

Listing 3.8 Retrieving Command-Line Arguments Using the Named Arguments Collection

  
1
2
3
4
5
6
7
8
Set colNamedArguments = WScript.Arguments.Named
strServer = colNamedArguments.Item("Server")
strPacketSize = colNamedArguments.Item("PacketSize")
strTimeout = colNamedArguments.Item("Timeout")
Wscript.Echo "Server Name: " & strServer
Wscript.Echo "Packet Size: " & strPacketSize
Wscript.Echo "Timeout (ms): " & strTimeout

The following command runs the script with three named arguments.

EchoNamedArgs.vbs /Server:HRServer01 /PacketSize:300 /Timeout:8000

This command produces the following output:

Server Name: HRServer01
Packet Size: 300
Timeout (ms): 8000

This command runs the same script with the order of the named arguments changed.

EchoNamedArgs.vbs /Timeout:8000 /PacketSize:300 /Server:HRServer01

This command produces the following output:

Server Name: HRServer01
Packet Size: 300
Timeout (ms): 8000

The output from the first command and the second command is the same. You can enter named arguments in any order without affecting the outcome of the script.

Named arguments are also useful when you want to include optional parameters within your scripts. The script in Listing 3.9 is similar to the script in Listing 3.8, but the PacketSize argument is an optional argument. If the script user does not enter a packet size, the script uses a default packet size.

The script uses the Exists method to check whether the user entered an argument named PacketSize. If the result of the test is True, the script proceeds to line 7. If the result of the test is False, the script proceeds to line 9, where the PacketSize variable is set to 100, using the DEFAULT_PACKET_SIZE constant.

Listing 3.9 Retrieving Command-Line Arguments and Using Default Argument Values

  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Const DEFAULT_PACKET_SIZE = 100
Set colNamedArguments = WScript.Arguments.Named
strServer = colNamedArguments.Item("Server")
If colNamedArguments.Exists("PacketSize") Then
 strPacketSize = colNamedArguments.Item("PacketSize")
Else
 strPacketSize = DEFAULT_PACKET_SIZE
End If
strTimeout = colNamedArguments.Item("Timeout")
Wscript.Echo "Server Name: " & strServer
If colNamedArguments.Exists("PacketSize") Then
 Wscript.Echo "Packet Size :" & strPacketSize
Else
 Wscript.Echo "Packet Size [default]: " & strPacketSize
End If
Wscript.Echo "Timeout (ms): " & strTimeout

Using Both Unnamed and Named Arguments

In most cases, you should not use both named and unnamed arguments in the same script. Using both types of arguments makes the required command-line syntax more difficult to remember. If your script accepts two or fewer arguments or multiple arguments of the same type, you might want to use unnamed arguments. If your script accepts three arguments of distinct types or has optional arguments, you should probably use named arguments.

Occasionally, however, it can be useful to mix named and unnamed arguments in a script. For example, if you have a script that has one required argument and a number of optional arguments, you can use an unnamed argument for the required argument and named arguments for all of the optional arguments. The following command contains a required server name (HRServer01) plus three optional arguments. In this command, the unnamed argument must be listed first, or the script will likely fail.

CheckServer.vbs HRServer01 /timeout:200 /logfile:serverlog.txt /verbose:true

Verifying Command-Line Arguments

Many of your scripts will require you to enter the required number and types of command-line arguments for the scripts to run correctly. You might need to perform two verifications on command-line arguments:

  • Number of arguments entered is within the acceptable range

  • Required arguments have been entered

Verifying the Number of Arguments Entered

Some scripts require a specific number of command-line arguments. For example, suppose you have a script that copies files from one computer to another. This script likely requires two, and only two, command-line arguments: the name of the source computer and the name of the target computer. Trying to run this script with one command-line argument or with three command-line arguments would not make any sense; there would be no way for the script to correctly determine the source and target computers.

In a situation such as this, one of the first things the script should do is verify that two command-line arguments were entered. This requires little effort on your part because arguments are returned as part of a collection, and collections typically include a Count property. The purpose of the Count property is to tell you how many items are in the collection. If Wscript.Arguments.Count equals 2, two arguments are in the collection.

The script in Listing 3.10 verifies the number of command-line arguments entered. The script accepts up to four arguments, any two of which are optional. Therefore, the user must enter at least two but no more than four arguments.

Listing 3.10 Verifying the Number of Command-Line Arguments Entered

  
1
2
3
4
5
6
7
8
9
iNumberOfArguments = WScript.Arguments.Count
If iNumberOfArguments >= 2 And iNumberOfArguments <= 4 Then
 Wscript.Echo iNumberOfArguments & " arguments entered. " & _
 "This is a valid number."
Else
 Wscript.Echo "Error: invalid number of arguments entered. " & _
 "Please enter 2, 3, or 4 arguments."
 Wscript.Quit
End If

In line 1 of Listing 3.10, the script uses WScript.Arguments.Count to determine the number of command-line arguments entered. The script stores this value in the iNumberOfArguments variable.

In line 2, the script uses iNumberOfArguments >=2 And iNumberOfArguments <=4 to test whether the user entered 2, 3, or 4 arguments:

  • If the result of the test is True, the script proceeds to line 3 and uses the Echo method to display a message indicating that the correct number of arguments was entered.

  • If the result of the test is False, the script proceeds to line 6 and uses the Echo method to display an error message indicating that the wrong number of arguments was entered.

The following command tries to run the script with more than four arguments.

CheckNumArgs.vbs HRServer01 RASServer01 SQLServer01 1000 300

This command produces the following output:

Error:   invalid number of arguments entered. Please enter 2, 3, or 4 arguments.

The output informs you that you have entered the wrong number of arguments. You are told that you should have entered between two, three, or four arguments instead of the five you entered.

This command runs the script with three arguments, an acceptable number for the script.

CheckNumArgs.vbs HRServer01 1000 300

This command produces the following output:

3 arguments entered. This is a valid number.

The output validates the fact that you have entered the correct number of arguments and that, as a result, the script is proceeding as expected. The script then displays the number of arguments you entered.

Verifying That All Required Arguments Are Entered

When you use command-line arguments in a script, the script should check to ensure that any required arguments have been entered before it proceeds. Unfortunately, WSH does not allow you to specify that an argument is required, and then notify you if the argument is not found. For example, if you run a command-line tool without a required argument, the tool typically will not run; instead, it displays usage instructions. Your scripts can do the same thing, but it is up to you to write code that checks the arguments collection and ensures that all the required arguments are present.

If you need to use required arguments in a script, it is recommended that you use named arguments. One advantage of using named arguments is that you can then use the Exists method to check whether an argument has been provided. For example, this line of code checks whether an argument named FolderName is present in the arguments collection. If the argument exists, the value 1 (True) will be echoed to the screen. Otherwise, the value 0 (False) will be displayed:

Wscript.Echo colNamedArguments.Exists("FolderName")

Suppose you enter the correct number of arguments but omit a required argument. The script in Listing 3.11 builds on the script in Listing 3.10. It uses the WshNamed collection Exists method to ensure that the named argument, Server, is among the arguments that you entered. In line 4, the script uses Not colNamedArgument.Exists("Server") to test whether the user has entered the named argument Server:

  • If the test reveals that the argument was not entered, the script proceeds to line 5. There the script uses the Echo method to display a message indicating that the named argument Server is required for the script to run. In line 6, Wscript.Quit is used to stop the script from running because the required argument, Server, was not entered.

  • If the test reveals that the argument was entered, the script proceeds to line 7.

    In lines 9 and 10, the script uses colNamedArguments.Item("Server") to retrieve the value of the Server named argument entered by the user. The script then displays a message constructed from this value. The message tells the user the value they entered for the Server named argument.

Listing 3.11 Verifying That All Required Arguments Are Entered

  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
iNumberOfArguments = WScript.Arguments.Count
Set colNamedArguments = WScript.Arguments.Named
If Not colNamedArguments.Exists("Server") Then
 Wscript.Echo "Usage: /Server:<servername> is required."
 Wscript.Quit
ElseIf iNumberOfArguments >= 2 Or iNumberOfArguments <= 4 Then
 Wscript.Echo iNumberOfArguments & " arguments entered"
 Wscript.Echo "including Server Name: " & _
 colNamedArguments.Item("Server")
Else
 Wscript.Echo "Usage: Please enter between 2 and 4 arguments."
 Wscript.Quit
End If

The following command tries to run the script without including the Server named argument.

CheckReqArgs.vbs 1000 300

This command produces the following output:

Usage: /Server:<servername> is required.

The output reflects the fact that you have not entered the Server named argument, which is required, by displaying a usage message.

This command runs the script with the required argument and an acceptable number of arguments.

CheckReqArgs.vbs /Server:HRServer01 1000 300

This command produces the following output:

3 arguments entered
including Server Name: HRServer01

The output reflects the fact that you have entered the correct number of arguments, including the required Server named argument. The script displays the value entered for the Server argument to reinforce the fact that this required argument was actually entered.