Previous Page
Next Page

Command-Line Arguments

Command-line arguments provide you with the ability to modify the execution of a script prior to running it.

Just the Steps

To implement command-line arguments

1.
On a new line, create a variable to hold WScript.Arguments.Item(0).

2.
Use the variable holding WScript.Arguments.Item(0) as a normal variable.


In the Ping.vbs script, which you examined in Chapter 2, "Looping Through the Script," and which appears in the next code listing (minus the comments), you use the variable strMachines to hold the target of the ping command. To ping other computers on the network, you have to modify the values within the quotation marks ("loopback;127.0.0.1;localhost" in this instance).

Note

In this and in other scripts, we leave out the Header information section (Option Explicit, On Error Resume Next, and the DIM for the variables.) This is done so we can focus on learning about command-line arguments and arrays (both rather complicated concepts). As indicated in Chapter 1, "Starting from Scratch;" before moving a script into "production," you really should make sure it is fully documented and that it runs without error (which will mean turning off On Error Resume Next by remarking it out), because this will save you much work if you need to modify the script at a later date.


Modifying the values might be an acceptable solution when you always ping the same computers, but when you want the flexibility of the normal command-line ping, a better script is clearly called forthe command-line argument.

Ping.vbs

strMachines = "loopback;127.0.0.1;localhost"
aMachines = Split(strMachines, ";")
For Each machine In aMachines
  Set objPing = GetObject("winmgmts:")._
  ExecQuery("select * from Win32_PingStatus where address = '" _
    & machine & "'")
  For Each objStatus In objPing
    If IsNull(objStatus.StatusCode) Or objStatus.StatusCode<>0 Then
      WScript.Echo("machine " & machine & " is not reachable")
    Else
      WScript.Echo("reply from " & machine)
    End If
  Next
Next

Making the Change

To modify the Ping.vbs script to accept multiple computer names prior to running, you need to make two modifications:

  • In the first non-commented line, delete "loopback;127.0.0.1;localhost".

  • Delete the addresses following strMachines = and add WScript.Arguments.Item(0).

That's all you need to do. The new script, named PingMultipleComputers.vbs, is shown here:

PingMultipleComputers.vbs

strMachines = WScript.Arguments.Item(0)
aMachines = Split(strMachines, ";")
For Each machine In aMachines
  Set objPing = GetObject("winmgmts:")._
  ExecQuery("select * from Win32_PingStatus where address = '"_
    & machine & "'")
  For Each objStatus In objPing
    If IsNull(objStatus.StatusCode) Or objStatus.StatusCode<>0 Then
      WScript.Echo("machine " & machine & " is not reachable")
    Else
      WScript.Echo("reply from " & machine)
    End If
  Next
Next

Running from the Command Prompt

To run the script, you go to the command prompt in the directory containing your script and type the following:

Cscript pingMultipleComputers.vbs localHost;127.0.0.1;loopback

You use this syntax because of the Split function you used on the second line, which expects a ";" to separate the computer names. If you change the ";" on the second line into a ";" as seen in the next code line, you can use the comma character to separate the machine names and have a slightly more orthodox command.

aMachines = Split(strMachines, ",")

Once this modification is made, the command-line syntax looks like the following:

Cscript pingMultipleComputers.vbs localHost,127.0.0.1,loopback

Quick Check

Q.

To implement command-line arguments, what action needs to be performed?

A.

Assign a variable to the command WScript.Arguments.Item(0).

Q.

What is the function of the Split command?

A.

The Split command can be used to parse a line of text based on a delimiter of your choosing.


No Arguments?

If a script tries to read command-line arguments not provided by the user, you get a Microsoft Visual Basic, Scripting Edition (VBScript) runtime error that makes a rather vague reference to "subscript out of range." This error is illustrated in Figure 4-1.

Figure 4-1. When a Visual Basic script tries to read a command-line argument that was not supplied, you get a "subscript out of range" error message


If another administrator is running your script and gets the "subscript out of range" error, that administrator will have a hard time determining the cause of the message. A quick search at http://support.microsoft.com returns dozens of support articles referencing "subscript out of range," but none of them tell you that VBScript requires command-line arguments. It behooves you to make sure users of your Visual Basic scripts are not presented with such unfriendly error messages. Let's look at handling that now.

Creating a Useful Error Message

When you supply command-line arguments for your scripts, the VBScript run time (called the Windows Scripting Host, or WSH for short) stores the arguments in an area of memory that is referenced by the WshArguments collection. This is nice because this storage location allows you to see how many command-line arguments are in there. Why is this important? It's important because when you know where the arguments are stored, and you know that they're kept in a collection, you can count the contents of that collection. For your script to run properly, there must be at least one argument supplied on the command line. You can make sure there is at least one argument by using the WScript.Arguments.Count method and putting it in an If...Then construction. To make the script easy to read, we place this logic in a subroutine. We call the subroutine first thing. If the value of the count is equal to zero, use WScript.Echo to send a message to the user that at least one argument is required. Once you make these modifications, CheckArgsPingMultipleComputers.vbs looks like the following:

CheckArgsPingMultipleComputers.vbs

Option Explicit
On Error Resume Next
Dim strMachines
Dim aMachines, machine
Dim objPing, objStatus
subCheckArgs 'uses the count method for WshArguments

strMachines = WScript.Arguments.Item(0)
aMachines = Split(strMachines, ";")
For Each machine in aMachines
Set objPing = GetObject("winmgmts:{impersonationLevel=impersonate}")._
ExecQuery("select * from Win32_PingStatus where address = '"_
& machine & "'")
For Each objStatus in objPing
   If IsNull(objStatus.StatusCode) or objStatus.StatusCode<>0 Then
   WScript.Echo("machine " & machine & " is not reachable")
   Else
   WScript.Echo("reply from " & machine)
   End If
Next
Next

Sub subCheckArgs
If WScript.Arguments.count = 0 Then
 WScript.Echo "You must enter a computer to ping" & VbCrLf & _
  "Try this: Cscript CheckArgsPingMultipleComputers.vbs " _
    & "127.0.0.1;localhost"
 WScript.Quit
End If
End sub

Quick Check

Q.

What is a possible cause of the "subscript out of range" error message when running scripts that are configured to use command-line arguments?

A.

The error message could be caused by trying to run a Visual Basic script that requires command-line arguments without supplying them.

Q.

List one method of creating useful error messages to trap the "subscript out of range" error.

A.

You can use an If...Then...Else construct to test WScript.Arguments.Count for the presence of a command-line argument. If none is present, you can then use the Else part to display a meaningful error to the user. In addition, it is important to note that you cannot always rely on the user putting in meaningful data. To solve this problem, you must check the input data to ensure it meets the criteria for correct input.


Note

There are two kinds of arguments: unnamed and named. With unnamed arguments when you supply a value to the script, the argument is interpreted according to its position on the command line. With named arguments, you supply a name for each argument. Each item in the collection of arguments has a name and is retrieved from the collection by name. Unnamed arguments are retrieved by index number.


Supply value for missing argument

1.
Open CheckArgsPingMultipleComputers.vbs from \My Documents\Microsoft Press\VBScriptSBS\ch04 in Microsoft Notepad or the script editor of your choice.

2.
Save the file as YourNameSupplyMissingArgument.vbs.

3.
Declare a variable colArgs to hold a collection of unnamed arguments.

4.
Set colArgs to hold a collection of unnamed arguments. This command will go right under the Header section of the script. The line of code will look like the following:

Set colArgs = WScript.Arguments.UnNamed

5.
In the subCheckArgs subroutine, modify If WScript.Arguments.count = 0 Then so that it uses the colArgs variable instead. The modified line of code will look like the following:

If colArgs.count = 0 Then

6.
Leave the remaining prompt the same.

7.
Delete the WScript.Quit line of code. We are not going to exit the script if no argument is supplied, rather we are going to supply a default value.

8.
On a new line, under the WScript.Echo command, assign the loopback adapter and local host to strMachines. The line will look like the following:

strMachines = "127.0.0.1;ocalhost"

9.
If the value of colArgs.count is greater than 0, then we want to use item(0) to assign to strMachines. This clause will look like the following:

Else
 strMachines = colArgs(0)

10.
Save and run the script. Supply a value at the command line; it should ping those machines.

11.
Run the script a second time. This time, do not supply a value for the command-line argument. The script should echo help that illustrates usage and then ping both the loopback and the localhost. If this is not the case, compare your script with CheckArgsPingMultipleComputersSupplyValue.vbs in the Chapter 4 folder.

Note

The Arguments collection is read-only. This is the reason for checking the number of arguments in the collection and then assigning a value to the variable that would have held the value if the argument had been present. This makes for more work in the script (as illustrated in the "Supply Value for Missing Argument" procedure), but the increased usability of the script is worth the effort. If the collection were not read-only, then we could have simply assigned the desired value directly to the argument once we detected that it was missing.



Previous Page
Next Page