Hey, Scripting Guy! Question

Hey, Scripting Guy! I’d like to have a script that accepts computer names as command-line arguments and then runs against each of those computers. However, if you don’t enter any command-line arguments, I’d like it to default to running against the local computer. Can you help me out here?

-- TS

SpacerHey, Scripting Guy! AnswerScript Center

Hey, TS. Sure, we can help you out here. Let’s say you started your hypothetical script by typing the following command at the command prompt:

cscript my_script.vbs atl-ws-01 atl-ws-02 atl-ws-03

In that case, you’d like the script to run against the three specified computers: atl-ws-01; atl-ws-02; and atl-ws-03. But what if you typed in a command with no command-line arguments, like this:

cscript my_script.vbs

In that case, you’d like the script to say, “Oh, no command-line arguments, huh? Ok, then I’ll just run against the local computer instead.”

So how do you do that? Well, you do that by using code similar to this:

If Wscript.Arguments.Count = 0 Then
    arrComputers = Array(".")
Else
    Dim arrComputers()
    For i = 0 to Wscript.Arguments.Count - 1
        Redim Preserve arrComputers(i)
        arrComputers(i) = Wscript.Arguments(i)
    Next
End If
 
For Each strComputer in arrComputers
    Set objWMIService = GetObject _
        ("winmgmts:\\" & strComputer & "\root\cimv2")
    Set colItems = objWMIService.ExecQuery _
        ("Select * from Win32_OperatingSystem")
    For Each objItem in colItems
        Wscript.Echo objItem.Caption
    Next
Next

Let’s take a moment to explain how this works. We start by seeing whether or not any command-line arguments were entered; we do that by checking the value of Wscript.Arguments.Count (as you might expect, this tells us the number of arguments that were supplied when the script started). Suppose Count is equal to 0. Well, that means you didn’t supply any command-line arguments. Therefore, we set the value of the array arrComputers to a dot (“.”). Why a dot? Well, in the wild and wonderful world of WMI, the dot represents the local computer.

And why an array? Well, we want to write as few lines of code as possible. By using an array, we don’t have to write one set of code that gets used when we don’t specify a command-line argument and a separate set of code that gets used when we do specify a command-line argument (or two). Instead, we use a simple If-Then statement to check the value of Wscript.Arguments.Count. As we noted, if the value is 0 (that is, if no command-line arguments were entered), we set the value of arrComputers to a single dot. We thus have an array consisting of a single item.

But what if Count does not equal 0? In that case, we want to take all the command-line arguments and stuff each of those into arrComputers. Here’s how we do that:

First, we create a dynamic array using this code: Dim arrComputers(). A dynamic array is an array in which we don’t specify the size in advance; instead, we dynamically grow the array as needed. We do that so that we don’t have to worry about how many command-line arguments were entered; we’ll just resize the array as needed to accommodate all of those arguments.

Next, we create a For Next loop that runs from 0 to Wscript.Arguments.Count - 1. This seems crazy, but we do this because the first item in a VBScript array is actually item 0; the last item, therefore, is the number of items minus 1. For example; suppose we have three items. The first item is item 0; the second is item 1; and the third is item 2 (3 - 1)

For each item, we resize the array using this code: Redim Preserve arrComputers(i). This sets the size of the array to the value of i (i is the loop variable, so it tells us which arguments in Wscript.Arguments we are working with). The first time through the loop, i is equal to 0, so we are - in effect - using this code: Redim Preserve arrComputers(0), which gives us an array with one element.

Incidentally, the Preserve part of this code ensures that we don’t lose all the existing each time we re-dimension the array. If we just said Redim arrComputers(), the array would get resized, but any data already in the array would be deleted.

We then add the argument in question to the array. If we supply atl-ws-01 and atl-ws-02 as command-line arguments, then at the end of this loop arrComputers will be an array with two elements: atl-ws-01 and atl-ws-02.

The rest is easy. We create a For-Each loop that loops through all the elements in the array arrComputers; as we know, arrComputers contains either a dot (representing the local machine) or a list of computer names pulled from the command-line arguments. Each time the loop runs in connects to the appropriate computer and retrieves the Caption property from the Win32_OperatingSystem class. And that’s all there is to it!