News

Managing Windows networks using scripts Part 2: Cleaning up

Mitch Tulloch

PREVIOUSLY: The basics

The first article of our guide to managing Windows networks using scripts introduced

    Requires Free Membership to View

some basic scripting concepts like objects, methods, and properties, and the goal of the article was to write a simple script that changed the IP address assigned to your network adapter. Here's what we came up with for our first script, which we called ChangeIPAddress.vbs:

strComputer = "."
arrIPAddress = Array("172.16.11.99")
arrSubnetMask = Array("255.255.255.0")
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colNetAdapters = objWMIService.ExecQuery("Select * from Win32_NetworkAdapterConfiguration")
For Each objNetAdapter in colNetAdapters
errEnableStatic = objNetAdapter.EnableStatic(arrIPAddress, arrSubnetMask)
Next

When I ran this script on my Windows server, it successfully changed the IP address of the machine from .45 to .99 as could be seen by running ipconfig before and after running the script. So far, so good.

Unfortunately, while the above script works, it's kind of "messy" as it's missing certain things that well-written scripts should have such as variable definitions, error handling, use input, and confirmation output. So let's "clean up" our script by adding these elements, and along the way we'll learn more about the basics of Windows scripting.

Variable definitions

The first thing we'll do to tidy up our script is to define the variables we're using in it. While VBScript lets you implicitly define variables simply by using them in a statement, it's always a good idea to explicitly declare your variables at the start of your script. Declaring a variable tells VBScript about its existence so that it can set aside memory for it. Why is declaring variables a good idea? Well, in a long script you're likely to make a typo or two, and if you type the name of a variable wrong then your script might not perform as expected. But if you explicitly declare variables at the start of a script, then any variable that is later implicitly declared in the script (like one caused by a typo) will generate a runtime error, and such errors can help you identify your typos and troubleshoot your scripts.

To let VBScript know that you're explicitly declaring all the variables in your script, add the following statement at the start of your script:

Option Explicit

If you just add this statement at the start of our ChangeIPAddress.vbs script and then run this script from a command prompt, you get the following result:

C:\Documents and Settings\Administrator.DC-1\Desktop>ChangeIPAddress.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

C:\Documents and Settings\Administrator.DC-1\Desktop\ChangeIPAddress.vbs(2, 1) Microsoft VBScript runtime error: Variable is undefined: 'strComputer'

What VBScript is saying here (or rather what the Windows Script Host's registered script engine for running VBScript scripts is saying) is that there is an error in line 2 of our script. What's in line 2? This:

strComputer = "."

Why does this generate a runtime error? Because we're assigning a value to a string variable (strComputer) that we haven't declared yet. So let's now add variable declarations for the variables we're using in our script:

Option Explicit
Dim objWMIService
Dim objNetAdapter
Dim strComputer
Dim arrIPAddress
Dim arrSubnetMask
Dim colNetAdapters
Dim errEnableStatic

strComputer = "."
arrIPAddress = Array("172.16.11.93")
arrSubnetMask = Array("255.255.255.0")
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colNetAdapters = objWMIService.ExecQuery("Select * from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE")
For Each objNetAdapter in colNetAdapters
errEnableStatic = objNetAdapter.EnableStatic(arrIPAddress, arrSubnetMask)
Next

Notice that when you use Option Explicit you have to declare all the variables in your script, including objects, strings, arrays, collections, variables for error codes, and so on. This may seem like a lot of hassle but believe me, once your scripts start running several pages in length, it can be a lifesaver as far as troubleshooting runtime errors goes. Note also that it doesn't matter what order you declare your variables in, just be sure to declare each variable before you use it. It's best usually to place all your variable declarations at the beginning of your script as a single section like we did above.

Error handling

Now that we've weeded out the typos (hopefully) from our script, when we run the revised script, it works. But what if it doesn't? For example, what if we modify our script to run it against a remote computer instead of the local machine (something I'll explain how to do in a future article) but the remote machine is not on the network? Again, a run time error (an error that happens while the script is being executed, as opposed to a syntax error that VBScript recognizes when it compiles the script before it runs it) will occur and the script will halt and display an error message similar to the one we showed previously, which of course is fine. But what if we write a script that is supposed to perform a number of actions? In this case, we might not want a run time error to halt the script-we might want the script to continue running so it can at least perform all the other actions it was intended to perform. A good example is a script that monitors settings on a number of computers but doesn't change these settings. In this case, you want the script to keep running even if one or more computers are not available.

The simplest way of handling run time errors is to ignore them when they occur. You can tell VBScript to do this by adding the following statement near the beginning of your script:

On Error Resume Next

A good place to add this is right after Option Explicit, so let's do that with our script. Of course, there are times when you might want to do something more with regard to error handling. For example, you might want to check for the existence of a run time error condition at some point in your script (for example, after trying to connect to the WMI service on a remote computer) so you can verify whether a certain action the script is supposed to perform has succeeded or not. Then, based on the result of testing for this error condition, you can decide what the script should do. For example, if an error has occurred, you might echo a message saying "Computer X not found" and then continue with the script. We'll look at error handling like this in detail in a future article of this series, but for now let's just add the statement above to ignore any run time errors that occur.

User input

What if we'd like to specify the new IP address for the machine when we run the script instead of hard-coding it into our script as 172.16.11.99? In that case, what we need to do is modify the script to enable us to provide user input when we run it. A nice way to do this would be if we could supply the arguments when we run our script from the command-line, for example typing ChangeIPAddress.vbs 172.16.11.188 should change the IP address of our network adapter to 172.16.11.188 and so on. Here's how to revise our script so we can do this:

Option Explicit
On Error Resume Next

Dim objWMIService
Dim objNetAdapter
Dim strComputer
Dim strAddress
Dim arrIPAddress
Dim arrSubnetMask
Dim colNetAdapters
Dim errEnableStatic

If WScript.Arguments.Count = 0 Then
Wscript.Echo "Usage: ChangeIPAddress.vbs new_IP_address"
WScript.Quit
End If

strComputer = "."
strAddress = Wscript.Arguments.Item(0)
arrIPAddress = Array(strAddress)
arrSubnetMask = Array("255.255.255.0")
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colNetAdapters = objWMIService.ExecQuery("Select * from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE")
For Each objNetAdapter in colNetAdapters
errEnableStatic = objNetAdapter.EnableStatic(arrIPAddress, arrSubnetMask)
Next

Let's take this apart piece by piece. First, we've declared one new variable:

Dim strAddress

This is a string variable that will contain the argument (IP address) we specify when we run the script. Next, we've added the following lines after our declaration section:

If WScript.Arguments.Count = 0 Then
Wscript.Echo "Usage: ChangeIPAddress.vbs new_IP_address"
WScript.Quit
End If

What does this do? The Arguments property of the WScript object returns the collection of arguments specified when we run a script. The Count method returns the number of arguments we entered, and what this piece of code does is check to see if we forgot to enter any arguments (number of arguments equals zero). If so, it echoes (displays) a message telling us how to properly use the script and then the script quits without going any further.

Finally, the former line:

arrIPAddress = Array("172.16.11.93")

where we hard-coded the new IP address to be assigned has now been replaced with these two lines:

strAddress = Wscript.Arguments.Item(0)
arrIPAddress = Array(strAddress)

The first line takes the first item (item number zero) of the WScript.Arguments collection and assigns it to the string variable strAddress. The second line then takes this strAddress and assigns it as the first element of the arrIPAddress array.

Let's see what happens when we run this new script, first without specifying an argument and then with an argument:

C:\Documents and Settings\Administrator.DC-1\Desktop>ipconfig

Windows IP Configuration

Ethernet adapter Local Area Connection:

Connection-specific DNS Suffix . :
IP Address. . . . . . . . . . . . : 172.16.11.31
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 172.16.11.1

C:\Documents and Settings\Administrator.DC-1\Desktop>ChangeIPAddress.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

Usage: ChangeIPAddress.vbs new_IP_address

C:\Documents and Settings\Administrator.DC-1\Desktop>ChangeIPAddress.vbs 172.16.11.188
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

C:\Documents and Settings\Administrator.DC-1\Desktop>ipconfig

Windows IP Configura