Part 3: Scripting Remote Network Management

This section illustrates how to write scripts to perform tasks on remote computers. It also highlights good scripting practices to follow when you run scripts remotely.

The value of scripting with VBScript, WSH, and WMI does not become fully apparent until you try to run scripts over a network on multiple computers. The techniques involved are not difficult, because remote operations are an intrinsic part of WMI. You can use all the techniques described in the previous section, “Scripting Basic TCP/IP Networking on Clients,” on one or more remote computers by making a few relatively simple modifications.

For more information about these and related techniques, see "Tales from the Script - November 2002: Running WMI Scripts Against Multiple Computers" at https://go.microsoft.com/fwlink/?LinkId=24786.

note.gif  Note
The WshController object of Windows Script Host provides another way to run scripts against remote computers. However, the WshController object is not included here because WMI provides simpler and more powerful ways to accomplish the scripting tasks discussed in this paper.

This section provides information about managing remote computers, including scripting steps and sample scripts for these topics:

  • Connecting to a remote computer and retrieving basic settings.

  • Connecting to a group of computers on a network.

  • Recording the data that you collect from network computers.

On This Page

Retrieving Basic Settings from a Remote Computer
Connecting to Groups of Computers on a Network
Reporting Data from Multiple Computers
Tools for Scripting Remote Network Management

Retrieving Basic Settings from a Remote Computer

Most system administrators need to manage remote computers on their network and can use scripts to great advantage for this purpose. The previous section discussed scripting techniques for retrieving and displaying settings on a local computer; this section shows how to modify those scripts for use on a remote computer. By using the techniques explained in the next two topics, you can use WMI to connect to a remote computer, and then retrieve and display the settings for that computer.

Using WMI to Connect to a Remote Computer

To use WMI to connect to a remote computer over the network, simply assign the name of the remote computer to the host variable used in the WMI object path. WMI handles the details of connecting to remote computers.

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer)

In the preceding example, WMI connects to the local computer. The period or dot character, (.) represents the local computer in WMI object paths. It connects to the default WMI namespace — typically root\cimv2 — by using the default impersonation level, "impersonate."

To connect to WMI on a remote computer, replace "." with the name of the remote computer:

strComputer = "client1"
Set objWMIService = GetObject("winmgmts:\\" & strComputer)

As on local computers, you must have sufficient administrative privileges on the remote computer to perform the actions that the script takes.

For more information about connecting to WMI, see the topic "Connecting to WMI Using the WMI Moniker," which is in the "WMI Scripting Primer" chapter of the Windows 2000 Scripting Guide at https://go.microsoft.com/fwlink/?LinkId=29993.

Getting the IP Addresses and Subnet Masks of a Remote Computer

The following script shows how to retrieve a couple of TCP/IP client settings from a remote computer. The code is almost identical to the code used in scripts that connect to WMI on the local computer; the only difference is that the name of an accessible remote computer is assigned to the strComputer variable.

Scripting Steps

Listing 13 retrieves the IPAddress and IPSubnet properties (both arrays) for each network adapter configuration on a remote computer.

  1. Invoke On Error Resume Next, which is the error-handling mechanism of VBScript.

  2. Create a variable to specify the remote computer name. This code is similar to that used in most scripts in this paper that run locally. However, the script assigns the string “client1” (the name of a remote computer) — in place of "." (the local computer) — to strComputer.

    To run this script, replace "client1" on line 3 with the name of an accessible remote computer on which you have administrative privileges.

  3. Use a GetObject call to connect to the WMI namespace root\cimv2, and set the impersonation level to “impersonate.” Here strComputer is concatenated into the object path so that the script binds to the \root\cimv2 namespace on the remote computer. The impersonation level and namespace are specified explicitly.

  4. Use the ExecQuery method to query the Win32_NetworkAdapterConfiguration class, filtering the WQL query with “WHERE IPEnabled = True.”

    This returns a collection consisting of all the network adapter configurations on the computer for which IP is enabled.

  5. For each network adapter configuration in the collection, retrieve the index number, description, IP addresses, and subnet masks.

Listing 13   Getip.vbs

  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

On Error Resume Next
 
strComputer = "client1"
Set objWMIService = GetObject("winmgmts:" _
 & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colNicConfigs = objWMIService.ExecQuery _
 ("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")
 
WScript.Echo VbCrLf & "Computer Name: " & strComputer
WScript.Echo " IP Addresses & Subnet Masks"
 
For Each objNicConfig In colNicConfigs
  WScript.Echo VbCrLf & "  Network Adapter " & objNicConfig.Index
  WScript.Echo "    " & objNicConfig.Description & VbCrLf 
  WScript.Echo "    IP Address(es):"
  For Each strIPAddress In objNicConfig.IPAddress
    WScript.Echo "        " & strIPAddress
  Next
  WScript.Echo "    Subnet Mask(s):"
  For Each strIPSubnet In objNicConfig.IPSubnet
    WScript.Echo "        " & strIPSubnet
  Next
Next

When you use Cscript.exe to run this script, output similar to the following is displayed in the command window:

C:\scripts>getip.vbs

 

Computer Name: client1

IP Addresses & Subnet Masks

 

  Network Adapter 1

    3Com 3C920 Integrated Fast Ethernet Controller (3C905C-TX Compatible) - Packet Scheduler Miniport

 

    IP Address(es):

        192.168.0.11

    Subnet Mask(s):

        255.255.255.0

Connecting to Groups of Computers on a Network

When you run WMI-based scripts to perform networking tasks on groups of computers, you can typically accomplish those tasks more efficiently and flexibly than with most Windows interface or command-line tools.

Whenever you must connect to remote computers, there are certain precautions you should use in your scripts. These precautions can help you avoid wasting time trying to run a script on computers that are unreachable or on which WMI is unavailable. WMI is not installed by default on operating systems before Windows 2000 and Windows Millennium Edition.

When you are connecting to remote computers, it is helpful to first check whether you can reach each computer over the network. The command-line tool Ping.exe is one traditional way of doing this. On Windows XP and later versions of Windows, WMI offers a new Win32_PingStatus class that closely duplicates the functionality of Ping.exe.

Because there is a greater chance of encountering problems when running a script on remote computers, it is often a good idea to use the error-handling mechanism in VBScript, which is called On Error Resume Next, so that network or remote problems do not crash the script. If the script encounters an error on one computer, this allows it to continue running on other computers.

You can also capture the error and then display or log it. For more information about error handling, see "Error Handling" in the "VBScript Primer" section of the Windows 2000 Scripting Guide at https://go.microsoft.com/fwlink/?LinkId=27641.

This section provides scripting steps and sample scripts on these topics:

  • Pinging network hosts before trying to run scripts on them.

  • Handling errors with VBScript.

  • Using an array to input a list of network hosts.

  • Obtaining the IP addresses and subnet masks of a group of remote computers.

  • Using a text file with a list of hosts as input.

  • Connecting to a subnet or range of IP addresses.

  • Other ways to provide input to scripts.

Pinging Network Hosts Before Trying to Run Scripts on Them

It is good practice to connect to each remote host to ensure that it is reachable before trying to do anything on it. If all the computers you have to ping are running Windows XP or Windows Server 2003, you can use the new WMI class Win32_PingStatus. Win32_PingStatus returns an object with 24 properties that supply extensive details about the ping packets that the class sends.

If earlier operating systems are involved, the TCP/IP command-line tool Ping.exe is the standard way to check connectivity. You can run Ping and command-line parameters with the Exec() method of the WshShell object. Ping sends a configurable number of ICMP broadcast packets to the host name or IP address and listens for replies. The script can parse the responses on STDOUT for the "reply from" string, which occurs only if the computer has responded to the ping.

note.gif  Note
The ping succeeds only if the routing infrastructure forwards the ping messages and the destination is not using a firewall that prevents the ping messages from being received.

Pinging a Single Network Host by Running Ping.exe from a Script

To determine whether a computer is accessible on the network before trying to connect to WMI and perform a task on it, a script can use WSH to call Ping.exe. VBScript provides string-handling functions that enable the script to parse the resulting StdOut stream to see if the remote computer responded and act accordingly.

Scripting Steps

Listing 14 illustrates how to run Ping.exe with the WshShell Exec() method.

  1. Invoke the VBScript error-handling mechanism, On Error Resume Next.

  2. Create a variable to specify the remote computer name.

    This script uses almost the same code used in most scripts in this paper. Here, though, it assigns “client1” (the name of the remote computer) to strComputer instead of “.” (the WMI name for the local computer). WMI also accepts IP addresses as the identifier of the remote computer. To run this script, replace "client1" with the name or IP address of an accessible remote computer on which you have administrative privileges.

  3. Create a WshShell object and assign it to objShell.

  4. Run the Exec method of objShell, passing it parameters that call for sending two echo requests, with a wait of 1000 milliseconds (one second) for each response, to the target computer. Assign the resulting object to objExec.

  5. Read the entire StdOut stream produced by the objExec object, convert it to lowercase to avoid case confusion, and assign the stream to the variable strPingResults.

  6. Call the InStr function of VBScript, which searches the first parameter, the string of results from the Ping for any occurrences of the second parameter, the literal string "reply from." If the literal is found, then Ping succeeded, and the target computer responded.

    InStr returns the character position in the first string in which the second string is found; if it is not found, InStr returns 0.

    The If...Then statement interprets any number except zero as True for its condition, the script then executes the lines of code that follow before Else (8–15). Because the target computer has responded, the script can connect to WMI on the target and display its name. This is just a simple example: after the script connects to the target computer, it can perform any set of WMI and ADSI tasks.

  7. If InStr does not find the string "reply from" and returns 0, then the remote computer has not responded to the Ping. In this case, the If...Then statement transfers script execution to the Else statement on line 16, and the script displays a message that the target did not respond to the ping. The script does not try to connect to WMI or perform the task on the remote computer because doing so would result in an error.

Listing 15   Ping.vbs

  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

On Error Resume Next
 
strTarget = "192.168.0.1" 'IP address or hostname
Set objShell = CreateObject("WScript.Shell")
Set objExec = objShell.Exec("ping -n 2 -w 1000 " & strTarget)
strPingResults = LCase(objExec.StdOut.ReadAll)
If InStr(strPingResults, "reply from") Then
  WScript.Echo strTarget & " responded to ping."
  Set objWMIService = GetObject("winmgmts:" _
   & "{impersonationLevel=impersonate}!\\" & strTarget & "\root\cimv2")
  Set colCompSystems = objWMIService.ExecQuery("SELECT * FROM " & _
   "Win32_ComputerSystem")
  For Each objCompSystem In colCompSystems
    WScript.Echo "Host Name: " & LCase(objCompSystem.Name)
  Next
Else
  WScript.Echo strTarget & " did not respond to ping."
End If

When you use Cscript.exe to run this script, output similar to the following is displayed in the command window:

C:\scripts>ping.vbs

192.168.0.1 responded to ping.

Host Name: server1

Pinging Multiple Network Hosts by Running Ping.exe from a Script

With a few more lines of code, a script can ping multiple computers one at a time before attempting to perform a task on each. The computer names are passed to the script in the form of an array, which is a simple way to accomplish this. However, the computer names can also be retrieved from a text file, spreadsheet, or database; or they can be enumerated from an Active Directory organizational unit (OU) by using only a little more code.

Scripting Steps

Listing 15 illustrates how to run Ping.exe with the WshShell Exec() method against multiple computers.

  1. Invoke On Error Resume Next, which is the error-handling mechanism for VBScript.

  2. Create an array with the VBScript Array function and add as elements the names or IP addresses of accessible computers on the network. The WMI service accepts both host names and IP addresses in the object path on line 12. Assign the array to the variable arrTargets.

  3. Use a For Each loop to iterate through each element in the array. For each computer name, perform the same steps performed on the remote computer in the previous example, Ping.vbs.

Listing 15   Ping-multi.vbs

  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

On Error Resume Next
 
arrTargets = Array("192.168.0.1", "192.168.0.11", "192.168.0.12", _
 "192.168.0.13")
 
For Each strTarget In arrTargets
  Set objShell = CreateObject("WScript.Shell")
  Set objExec = objShell.Exec("ping -n 2 -w 1000 " & strTarget)
  strPingResults = LCase(objExec.StdOut.ReadAll)
  If InStr(strPingResults, "reply from") Then
    WScript.Echo VbCrLf & strTarget & " responded to ping."
    Set objWMIService = GetObject("winmgmts:" _
     & "{impersonationLevel=impersonate}!\\" & strTarget & "\root\cimv2")
    Set colCompSystems = objWMIService.ExecQuery("SELECT * FROM " & _
     "Win32_ComputerSystem")
    For Each objCompSystem In colCompSystems
      WScript.Echo "Host Name: " & LCase(objCompSystem.Name)
    Next
  Else
    WScript.Echo VbCrLf & strTarget & " did not respond to ping."
  End If
Next

When you use Cscript.exe to run this script, output similar to the following is displayed in the command window:

C:\scripts>ping-multi.vbs

 

192.168.0.1 responded to ping.

Host Name: server1

 

192.168.0.11 responded to ping.

Host Name: client1

 

192.168.0.12 responded to ping.

Host Name: client2

 

192.168.0.13 did not respond to ping.

Pinging a Single Network Host by Using the Win32_PingStatus Class

On Windows XP and Windows Server 2003, the new WMI class Win32_PingStatus can return more details of the ping operation than those provided by Ping.exe. However, you can only use this WMI class on a network that is running just these two operating systems.

In such a situation, this script can serve as a template for testing a single remote computer for connectivity with a ping before attempting to connect to WMI and perform tasks on it.

The StatusCode property of Win32_PingStatus returns the status codes shown in Table 6. Their data type is uint32 and they are read-only. To make this script more user-friendly, you can translate the status codes into the descriptive string that appears in Table 6.

Table 6   Win32_Pingstatus Status Codes

Value

Description

0

Success

11001

Buffer Too Small

11002

Destination Net Unreachable

11003

Destination Host Unreachable

11004

Destination Protocol Unreachable

11005

Destination Port Unreachable

11006

No Resources

11007

Bad Option

11008

Hardware Error

11009

Packet Too Big

11010

Request Timed Out

11011

Bad Request

11012

Bad Route

11013

TimeToLive Expired Transit

11014

TimeToLive Expired Reassembly

11015

Parameter Problem

11016

Source Quench

11017

Option Too Big

11018

Bad Destination

11032

Negotiating IPSEC

11050

General Failure

Scripting Steps

Listing 16 illustrates how to use the Win32_PingStatus class to test the connectivity of a remote computer and display information about the ping results that the properties of this class can return.

  1. Invoke the VBScript error-handling mechanism, On Error Resume Next.

  2. Create a variable to specify the name of the computer that runs the script.

  3. Create a variable to specify the name of the target computer to be pinged.

  4. Connect to the WMI service on the computer where you run the script.

    This example runs the script on the local computer (".") and targets the local loopback address ("127.0.0.1"), but you can run this script on a remote computer and ping another remote computer.

  5. Call the ExecQuery method of the WMI service object, passing it a WQL query that requests all properties (*) from the instance of Win32_PingStatus where the address is that of the target computer. Assign the resulting collection of instances (in this example, just one instance results) to the variable colPings.

    The Win32_PingStatus is unusual within WMI in that you do not call a method to perform actions with it. Rather, you simply query the class, filtering with WHERE for the instance where the value of Address, which is one of the key properties, is the name or IP address of the target computer. You can also filter for several other key properties to configure the ping. By running such a query, the script initiates the ping operation.

  6. If no error occurs in querying the Win32_PingStatus class, iterate through the collection of ping objects (there is only one by nature of the query).

  7. If no error occurs in iterating through the collection of ping objects, check the status code returned by the ping object.

  8. If the status code is 0, which indicates that the target responded to the ping, display several of the properties returned by the ping object.

  9. If an error occurs, either in querying the Win32_PingStatus class or in iterating through the collection of ping objects, clear the status code and display the status code description.

Listing 16   Pingstatus.vbs

  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

On Error Resume Next
 
strComputer = "."
strTarget = " client1" 'IP address or hostname
Set objWMIService = GetObject("winmgmts:" _
 & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colPings = objWMIService.ExecQuery _
 ("Select * From Win32_PingStatus where Address = '" & strTarget & "'")
If Err = 0 Then
  Err.Clear
  For Each objPing in colPings
    If Err = 0 Then
      Err.Clear
      If objPing.StatusCode = 0 Then
        Wscript.Echo strTarget & " responded to ping."
        Wscript.Echo "Responding Address: " & objPing.ProtocolAddress
        Wscript.Echo "Responding Name: " & objPing.ProtocolAddressResolved
        Wscript.Echo "Bytes Sent: " & objPing.BufferSize
        Wscript.Echo "Time: " & objPing.ResponseTime & " ms"
        Wscript.Echo "TTL: " & objPing.ResponseTimeToLive & " seconds"
      Else
        WScript.Echo strTarget & " did not respond to ping."
        WScript.Echo "Status Code: " & objPing.StatusCode
      End If
    Else
      Err.Clear
      WScript.Echo "Unable to call Win32_PingStatus on " & strComputer & "."      
    End If
  Next
Else
  Err.Clear
  WScript.Echo "Unable to call Win32_PingStatus on " & strComputer & "."
End If

When you use Cscript.exe to run this script, output similar to the following is displayed in the command window:

C:\scripts>pingstatus.vbs

client1 responded to ping.

Responding Address: 192.168.0.11

Responding Name:

Bytes Sent: 32

Time: 0 ms

TTL: 128 seconds

Pinging Multiple Network Hosts by Using the Win32_PingStatus Class

This script uses the Win32_PingStatus class to ping a list of computers specified in an array. If the host on which you run the script is running an operating system that is earlier than Windows XP, the script captures the error and falls back to the WSH Exec method of pinging.

Scripting Steps

Listing 17 illustrates how to use the Win32_PingStatus class to test the connection with multiple computers.

  1. Invoke the VBScript error-handling mechanism, On Error Resume Next.

  2. Create an array of strings to specify the names of the target computers to be pinged. Each element must be the name or IP address of an accessible network host.

  3. Use a For Each loop to iterate through the array containing the names of the target computers.

  4. On each target computer, call the ExecQuery method of the WMI service object, passing it a WQL query that requests all properties (*) from the instance of Win32_PingStatus where the address is that of that target computer. Assign the resulting collection of instances (in this example, just one instance) to the variable colPings.

    The Win32_PingStatus is unusual within WMI because you do not call a method to perform actions with it. Rather, you simply query the class, filtering with WHERE for the instance where the value of Address, which is one of the key properties, is the name or IP address of the target computer. You can also filter for several other key properties to configure the ping. By executing such a query, the script initiates the ping operation.

  5. If the attempt to query Win32_PingStatus returns no error, iterate through the collection of ping objects (there is only one by nature of the query) and check the StatusCode property of the ping object.

  6. If the value of StatusCode is 0, the ping succeeded. Display several of the properties returned and call the subroutine GetName. GetName displays the Name property of the Win32_ComputerSystem class. This is useful because this script can use the IP address of the computer as the identifier on the list of target computers.

  7. If the StatusCode property is not 0, the target computer did not respond to the ping. Display the value of StatusCode as an error message.

  8. If an error occurred in trying to query Win32_PingStatus clear the error. This error probably means that Win32_PingStatus was not available on the target computer.

  9. Call the function ExecPing.

    • ExecPing uses the same code as that used by Ping.vbs to run the command-line tool Ping.exe and interpret its output.

    • ExecPing returns a Boolean value that is True if the ping includes the string "reply from" in the output text that it returns (in other words, if the ping succeeds), and False if "reply from" is not present.

  10. If ExecPing returns True, call GetName to display the name of the target computer.

    GetName obtains the name of the computer from the Name property of Win32_ComputerSystem.

Listing 17   Pingstatus-multi.vbs

  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

On Error Resume Next
 
strComputer = "."
arrTargets = Array("192.168.0.1", "192.168.0.11", "192.168.0.12", _
 "192.168.0.13")
 
Set objWMIService = GetObject("winmgmts:" _
 & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
 
For Each strTarget In arrTargets
 
  Set colPings = objWMIService.ExecQuery _
   ("Select * From Win32_PingStatus where Address = '" & strTarget & "'")
  If Err = 0 Then
    Err.Clear
    For Each objPing in colPings
      If objPing.StatusCode = 0 Then
        Wscript.Echo VbCrLf & strTarget & " responded to ping."
        Wscript.Echo "Responding Address: " & objPing.ProtocolAddress
        Wscript.Echo "Responding Name: " & objPing.ProtocolAddressResolved
        Wscript.Echo "Bytes Sent: " & objPing.BufferSize
        Wscript.Echo "Time: " & objPing.ResponseTime & " ms"
        Wscript.Echo "TTL: " & objPing.ResponseTimeToLive & " seconds"
        GetName
      Else
        WScript.Echo VbCrLf & strTarget & " did not respond to ping."
        WScript.Echo "Status Code: " & objPing.StatusCode
      End If
    Next
  Else
    Err.Clear
    If ExecPing = True Then
      GetName
    End If
  End If
 
Next
 
'******************************************************************************
 
Function ExecPing
 
  Set objShell = CreateObject("WScript.Shell")
  Set objExec = objShell.Exec("ping -n 2 -w 1000 " & strTarget)
  strPingResults = LCase(objExec.StdOut.ReadAll)
  If InStr(strPingResults, "reply from") Then
    WScript.Echo VbCrLf & strTarget & " responded to ping."
    ExecPing = True
  Else
    WScript.Echo VbCrLf & strTarget & " did not respond to ping."
    ExecPing = False
  End If
 
End Function
 
'******************************************************************************
 
Sub GetName
 
  Err.Clear
  Set objWMIServiceRemote = GetObject("winmgmts:" _
   & "{impersonationLevel=impersonate}!\\" & strTarget & "\root\cimv2")
  If Err = 0 Then
    Err.Clear
    Set colCompSystems = objWMIServiceRemote.ExecQuery("SELECT * FROM " & _
     "Win32_ComputerSystem")
    For Each objCompSystem In colCompSystems
      WScript.Echo "Host Name: " & LCase(objCompSystem.Name)
    Next
  Else
    Err.Clear
    WScript.Echo "Unable to connect to WMI on " & strTarget & "."
  End If
 
End Sub

When you use Cscript.exe to run this script, output similar to the following is displayed in the command window:

C:\scripts>pingstatus-multi.vbs

 

192.168.0.1 responded to ping.

Responding Address: 192.168.0.1

Responding Name:

Bytes Sent: 32

Time: 0 ms

TTL: 128 seconds

Host Name: server1

 

192.168.0.11 responded to ping.

Responding Address: 192.168.0.11

Responding Name:

Bytes Sent: 32

Time: 0 ms

TTL: 128 seconds

Host Name: client1

 

192.168.0.12 responded to ping.

Responding Address: 192.168.0.12

Responding Name:

Bytes Sent: 32

Time: 0 ms

TTL: 128 seconds

Host Name: client2

 

192.168.0.13 did not respond to ping.

Status Code: 11010

Handling Errors with VBScript

Scripts should also handle errors that may be generated when connecting to WMI on remote computers — particularly if some computers are running Windows 95, Windows 98, or Windows NT 4.0, which may not have WMI installed. You can use the VBScript On Error Resume Next statement in conjunction with the built-in Err object to do this.

The Getip-multi.vbs script, which follows, and other sample scripts in this paper, illustrate how to do this. Note that after calling the Err object, it is important to use the Err.Clear method to ensure that error information for one computer is deleted before checking for it on the next computer.

For more information about error handling in scripts, see “Error Handling” in the “VBScript Primer” section of the Windows 2000 Scripting Guide at https://go.microsoft.com/fwlink/?LinkId=27641.

Using an Array to Input a List of Network Hosts

The simplest way to input a list of network hosts is to use an array of computer names, which can be host names, IP addresses, or a mixture. You can then use a For Each statement to iterate through each element of the array, that is, each computer, and retrieve data from, or perform actions on, each element.

The Getip-multi.vbs script and other scripts in this paper illustrate this approach.

Obtaining the IP Addresses and Subnet Masks of a Group of Remote Computers

This script uses the algorithm from Ping.vbs and Ping-multi.vbs to try to connect with remote computers before performing any operations on them. This ensures that the script will run against all versions of Windows that include WMI. If all your hosts run Windows XP and Windows Server 2003, you can substitute the code from Pingstatus.vbs and Pingstatus-multi.vbs.

After pinging the remote computers, this script attempts to bind to the WMI service and then checks for an error. On computers running pre-Windows 2000 or non-Windows based operating systems, WMI may not be present, and the script handles the error, displaying an error message before moving on to the next computer.

If your network includes older or non-Windows operating systems, it is a good idea to use this code in scripts that connect to multiple computers. Because the script uses On Error Resume Next, it will not crash if it encounters an error but simply moves on to the next line that does not generate an error.

Scripting Steps

Listing 18 retrieves the IPAddress and IPSubnet properties (both arrays) for each network adapter configuration on a remote computer.

  1. Invoke the VBScript error-handling mechanism, On Error Resume Next.

  2. Create a variable and assign an array of remote computer names to it. The names can be in the form of either host names or IP addresses or a mixture. To run this script, change the existing names to those of accessible remote computers on your network on which you have administrative privileges.

  3. Call the Exec() method of the WshShell object to run Ping.exe against each remote computer before trying to connect to WMI on it. Running "ping -n 2 -w 1000" sends two echo requests and waits one second (1000 milliseconds) for a reply. If the ping returns an answer, continue with the script. If not, display an error message (lines 50–53).

  4. Use a GetObject() call to connect to the WMI namespace root\cimv2, and set the impersonation level to “impersonate.”

  5. Check to see if an error has occurred on the GetObject() call (line 18).

    • If no error occurs, continue with the script.

    • If an error occurs, display the number, source, and description (lines 40–46).

  6. Call the ExecQuery method to query the Win32_NetworkAdapterConfiguration class, filtering the WQL query for those instances where IPEnabled is True.

    This returns a collection consisting of all the network adapter configurations on the computer for which IP is enabled.

  7. For each network adapter configuration in the collection, display the Index and Description properties followed by the IP addresses and subnet masks.

Listing 18   Getip-multi.vbs

  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

On Error Resume Next
 
arrComputers = Array("server1", "client1", "server2", "client2")
 
For Each strComputer In arrComputers
 
' Ping remote computer. If inaccessible, display error message.
  Set objShell = CreateObject("WScript.Shell")
  Set objScriptExec = objShell.Exec("ping -n 2 -w 1000 " & strComputer)
  strPingResults = LCase(objScriptExec.StdOut.ReadAll)
  If InStr(strPingResults, "reply from") Then
 
    WScript.Echo VbCrLf & "Host Name: " & strComputer
    Set objWMIService = GetObject("winmgmts:" _
     & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
' Test for success in binding to WMI.
    If Err = 0 Then
      Set colNicConfigs = objWMIService.ExecQuery("SELECT * FROM " & _
       "Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")
      For Each objNicConfig In colNicConfigs
        WScript.Echo VbCrLf & "  Network Adapter " & objNicConfig.Index
        WScript.Echo "    " & objNicConfig.Description & VbCrLf
        WScript.Echo "    IP Address(es):"
        For Each strIPAddress In objNicConfig.IPAddress
          WScript.Echo "        " & strIPAddress
        Next
        WScript.Echo "    Subnet Mask(s):"
        For Each strIPSubnet In objNicConfig.IPSubnet
          WScript.Echo "        " & strIPSubnet
        Next
      Next
    Else
      Wscript.Echo "Error: Unable to connect to WMI." & VbCrLf & _
       "Error Number: " & Err.Number & VbCrLf & _
       "Error Source: " & Err.Source & VbCrLf & _
       "Error Description: " & Err.Description
      Err.Clear
    End If
 
  Else
 
    WScript.Echo VbCrLf & "Host Name: " & strComputer & VbCrLf & _
     "  Unable to connect."
 
  End If
 
Next

When you use Cscript.exe to run this script, output similar to the following is displayed in the command window:

C:\scripts>getip-multi.vbs

 

Host Name: server1

 

  Network Adapter 12

    3Com EtherLink XL 10/100 PCI For Complete PC Management NIC (3C905C-TX) #2 -

Packet Scheduler Miniport

 

    IP Address(es):

        192.168.0.1

    Subnet Mask(s):

        255.255.255.0

 

Host Name: client1

 

  Network Adapter 1

    3Com 3C920 Integrated Fast Ethernet Controller (3C905C-TX Compatible) - Pack

et Scheduler Miniport

 

    IP Address(es):

        192.168.0.11

    Subnet Mask(s):

        255.255.255.0

 

Host Name: server2

  Unable to connect.

 

Host Name: client2

 

  Network Adapter 1

    3Com 3C918 Integrated Fast Ethernet Controller (3C905B-TX Compatible)

 

    IP Address(es):

        192.168.0.12

    Subnet Mask(s):

        255.255.255.0

Using a Text File with a List of Hosts as Input

To make the list of hosts against which a script runs more easily maintainable than an array, you can put the list in a text file. You can read the text file into the script with the FileSystemObject of Script Runtime (a component that ships with WSH). Several scripts in this paper, including Dns-move.vbs and Addclient.vbs, illustrate how to do this.

Connecting to a Range of IP Addresses

If a script is to be run against a range of IP addresses, such as a subnet, you can use simple scripting techniques to construct the range programmatically. This is possible because you can use an IP address as well as a host name in the WMI object path when you connect to a remote computer. After connecting, you can use other means, such as the Name property of the Win32_Computer class, to retrieve the host name. For an illustration of this technique, see the GetName subroutine in Pinstatus-multi.vbs earlier in this paper.

For an example of connecting to a range of IP addresses, see Dhcp-enable-subnet.vbs in "Scenario: Allocating IP Addresses on a Subnet" later in this paper.

Other Ways to Provide Input to Scripts

Other more complex and powerful methods for retrieving a list of computers programmatically include:

  • Using ADSI to connect to an Active Directory container, such as an OU, and then iterating through the contents of the container.

  • Using spreadsheets and databases as input to WMI and ADSI scripts.

These techniques enable a script to obtain more information about each computer than just host names or IP addresses. For more information about these techniques, see "Tales from the Script - November 2002: Running WMI Scripts Against Multiple Computers" at https://go.microsoft.com/fwlink/?LinkId=24786.

Reporting Data from Multiple Computers

After collecting information from multiple computers on a network, you may often want to save the data in some form. The simplest way to log data is to redirect the script output to a text file. You can use the command-shell redirection operator, the right angle bracket (>), to redirect script output to a file. To append output to an existing file, use two right angle brackets (>>). For example, the following command saves the output of Ipsettings.vbs to a new text file called Ipsettings.txt:

ipsettings.vbs > ipsettings.txt

You can also use the FileSystemObject of the Script Runtime library to create files and then write to them. For more information about using the FileSystemObject for script input, see "FileSystemObject" in the Windows 2000 Scripting Guide at https://go.microsoft.com/fwlink/?LinkId=27642. The Script Runtime library is included in all versions of Windows that contain Windows Script Host and all downloads of Windows Script.

A slightly more versatile way to output information is to format and write it as a comma-delimited text file with a .csv extension. You can open .csv files with a spreadsheet. Microsoft Excel also provides an extensive scripting object model that allows you to create .xls files.

Finally, ActiveX Data Objects (ADO) provides a way for scripts that use VBScript and WSH to interact directly with databases. Even without connecting to a database, ADO disconnected record sets provide a convenient way to sort and manipulate data.

For more information about these methods of handling output, see “Tales from the Script - April 2003: Script Output that Sticks Around” in the TechNet Script Center at https://go.microsoft.com/fwlink/?LinkId=24788. Also see the following Windows 2000 Scripting Guide topics:

Tools for Scripting Remote Network Management

When you manage remote networks, several Windows tools and registry keys can help you with scripting. Table 7 lists the available tools and provides information about where you can access them.

Table 7   Tools for Remote Network Management

Technology

Tool

Where Available

Command-line tools

Ping.exe

Windows operating systems1

Command-line tools

Remote.exe

Windows Server 2003 Support Tools

Command-line tools

Remote Command Service (Rcmd.exe and Rcmdsvc.exe)

Windows 2000 Resource Kit

Command-line tools

Remote Console

Windows 2000 Resource Kit

Command-line tools

Rsh.exe and Rshsvc.exe: TCP/IP Remote Shell Service

Windows 2000 Resource Kit

Command-line tools

Telnet.exe

Windows operating systems

Command-line tools

Wsremote.exe

Windows XP Support Tools

WSH

WshController

 

WMI

StdRegProv

 

WMI

Win32_ComputerSystem

 

WMI

Win32_NetworkAdapterConfiguration

 

WMI

Win32_NetworkAdapter

 

WMI

Win32_OperatingSystem

 

WMI

Win32_PingStatus

Windows XP and Windows Server 2003 only

1 Windows 2000, Windows XP, and Windows Server 2003. May also be present on other versions of Windows.

Table 8 lists the registry subkeys that you can use for scripting remote networks.

caution.gif  Caution
Incorrectly editing the registry may severely damage your system. Before making changes to the registry, you should back up any valued data on the computer.

Table 8   Registry Subkeys Related to Scripting Remote Network Management

Registry Subkeys

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces
\{AdapterIdentifier}

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Dhcp\Parameters