Managing Windows Networks Using Scripts - Part 2: Cleaning Up

by [Published on 1 Nov. 2006 / Last Updated on 1 Nov. 2006]

This article continues introducing readers to the basics of managing Windows networks using scripts by extending the script developed in the previous article.

If you would like to read the other parts in this article series please go to:

Last month I began a new series of articles here on WindowsNetworking.com intended to demonstrate how to manage different aspects of Windows networks using scripts. The first article introduced 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


Get your copy of Windows Server Hacks!

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 Configuration

Ethernet adapter Local Area Connection:

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

So far, so good!

Confirmation Output

Next, I'm getting a bit tired having to type ipconfig after running my script to see if it did what I expected it to do. Is there any way of checking the result of the script without doing this? Yes there is! Note the following lines of our script:

For Each objNetAdapter in colNetAdapters
     errEnableStatic = objNetAdapter.EnableStatic(arrIPAddress, arrSubnetMask)
Next

While the purpose of this code is to change the IP address assigned to the network adapter using the objNetAdapter.EnableStatic method, I noted in my previous article of this series that we needed to use an err- variable (here errEnableStatic) as a place to store the error code returned when the method is run. A list of possible error codes that can be returned by the EnableStatic Method of the Win32_NetworkAdapterConfiguration Class is found here on MSDN, and from this list we can see that a returned error code of zero means the operation was successful (i.e. the adapter's IP address was successfully changed). The simplest way to check for this is to echo this error code by adding this line at the end of our script:

Wscript.Echo errEnableStatic

Let's run our script again and see this:

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

0

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.237
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 172.16.11.1

Sure enough, an error code of 0 indicates the IP address was successfully changed. A bit of a nicer method would be to display a message instead by replacing this echo statement with the following:

If errEnableStatic=0 Then
     Wscript.Echo "Adapter's IP address has been successfully changed to " & strAddress
Else
     Wscript.Echo "Changing the adapter's address was not successful. Error code " & errEnableStatic
End If

Let's add this to the end of our script and try running the script twice, once with a proper IP address and once with nonsense:

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

Adapter's IP address has been successfully changed to 172.16.11.173

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

Changing the adapter's address was not successful. Error code 70

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

Conclusion

The final thing we'll want to do to clean up our script is to add a few comments to document our script. This is always a good idea so that when you pull the script out of your toolbox a year later and want to use it or modify it, you can quickly figure out what it's supposed to do. Here is our final, cleaned-up script for changing the IP address of the network adapter on our machine:

'=========================
' NAME: ChangeIPAddress.vbs
'
'AUTHOR: Mitch Tulloch
'DATE: October 2006
'
ARGUMENTS:
'1. new_IP_address
'=========================-

Option Explicit
On Error Resume Next

Dim objWMIService
Dim objNetAdapter
Dim strComputer     ' Can specify IP address or hostname or FQDN
Dim strAddress     'Contains the new IP address
Dim arrIPAddress
Dim arrSubnetMask
Dim colNetAdapters
Dim errEnableStatic

'Check for missing arguments

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

'Display result or error code

If errEnableStatic=0 Then
     Wscript.Echo "Adapter's IP address has been successfully changed to " & strAddress
Else
     Wscript.Echo "Changing the adapter's address was not successful. Error code " & errEnableStatic
End If

If you would like to read the other parts in this article series please go to:

Advertisement

Featured Links