3.7 Network components providers


3.7 Network components providers

3.7.1 Ping provider

The Ping provider is a bit unusual, because it only supports the "Get" operation. Trying an "enumeration" operation makes no sense, since this provider reflects the result of the PING command execution. This provider only supports one class: the Win32_PingStatus class. (See Table 3.58.)

Table 3.58: The Ping Providers Capabilities

Provider Name

Provider Namespace

Class Provider

Instance Provider

Method Provider

Property Provider

Event Provider

Event Consumer Provider

Support Get

Support Put

Support Enumeration

Support Delete

Windows Server 2003

Windows XP

Windows 2000 Server

Windows 2000 Professional

Windows NT 4.0

PING Provider

WMIPingProvider

Root/CIMv2

X

X

X

X

X

Creating an instance of the Win32_PingStatus class to ping a host is not really useful, but combining this functionality with some other WMI capabilities can produce a useful tool to determine if a system is still alive on the network. If we use a script code to create and delete an Interval Timer, combined with some asynchronous event notifications, we can develop a script that will ping a selected host on a regular time interval basis. Moreover, we can send an email alert to the Administrator if the PING reply is not successful by reusing some of the function previously developed (i.e., SendAlert() function). The script reflects the PING.Exe command-line utility with some extra parameters specific to the script functionalities. The script command-line parameters are as follows:

 C:\>WMIPingMonitor.wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMIPingMonitor.wsf host [/a[+|-]] [/l:value] [/f[+|-]] [/i:value] [/v:value] [/r:value]                                [/s:value] [/j:value] [/k:value] [/w:value] [/interval:value]                                [/verbose[+|-]] [/Alert[+|-]] [/Machine:value] [/User:value]                                [/Password:value] Options: host     : IP Address or host name of the system to ping. a        : Resolve addresses to hostnames. l        : Send buffer size (size). f        : Set Don't Fragment flag in packet. i        : Time To Live (TTL). v        : Type Of Service (TOS) (0=default, 2=Minimize Monetary Cost,            4=Maximize Reliability, 8=Maximize Throughput, 16=Minimize Delay). r        : Record route for count hops (count). s        : Timestamp for count hops (count). j        : Loose source route along host-list (host-list). k        : Strict source route along host-list (host-list). w        : Timeout in milliseconds to wait for each reply (timeout). interval : Time interval between PING commands (in seconds). verbose  : Show all Win32_PingStatus properties. Alert    : Send an email in case of PING failure. Machine  : Determine the WMI system to connect to. (default=LocalHost) User     : Determine the UserID to perform the remote connection. (default=none) Password : Determine the password to perform the remote connection. (default=none) Examples:       WMIPingMonitor.wsf 10.10.10.1       WMIPingMonitor.wsf 10.10.10.1 /a+ /l:32 /f+ /i:80 /v:4 /r:2 /s:1       WMIPingMonitor.wsf 10.10.10.1 /a+ /l:32 /f+ /i:80 /v:4 /r:5 /s:1 /Interval:10       WMIPingMonitor.wsf 10.10.10.1 /a+ /l:32 /f+ /i:80 /v:4 /r:6 /s:1 /Interval:10 /Verbose+       WMIPingMonitor.wsf 10.10.10.1 /a+ /l:32 /f+ /i:80 /v:4 /r:6 /s:1 /Verbose+ /Alert-       WMIPingMonitor.wsf 10.10.10.1 /j "10.10.10.254,192.1.1.1"       WMIPingMonitor.wsf 10.10.10.1 /k "10.10.10.254,192.1.1.1"       WMIPingMonitor.wsf 10.10.10.1 /a+ /w:10000       WMIPingMonitor.wsf 10.10.10.1 /a+ /Machine:NET-DPEN6400A.LissWare.Net                                         /Account:LISSWARENET\Administrator /Password:password 

If we use the following command-line parameters:

 C:\>WMIPingMonitor.wsf 16.174.12.1 /a+ /1:32 /f+ /i:80 /v:4 /r:3 /s:1 /verbose+ 

we will ping a host with the 16.174.12.1 IP address, request a host name resolution (/a+), use a packet size of 32 bytes (/l:32), ensure that the packet is not fragmented (/f+), request a time to live (TTL) of 80 seconds, request a service for a maximum reliability (/v:4), limit the record route for count hops to 3 (/r:3) and the timestamp for count hops to 1 (/s:1). The presence of the /Verbose+ switch forces the script to display all properties of the Win32_PingStatus class. The obtained output would be as follows:

  1:   C:\>WMIPingMonitor.wsf 16.174.12.1 /a+ /1:32 /f+ /i:80 /v:4 /r:3 /s:1 /verbose+  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:   PING timer created.  6:   Waiting for events...  7:  8:   Sunday, 09 December, 2001 at 18:38:29.  9:     WMIPING host '16.174.12.1' started ... 10:     Host '16.174.12.1' successfully contacted. 11: 12:     - Win32_PingStatus ------------------------------------------------------------- 13:     *Address: .............................. 16.174.12.1 14:     *BufferSize: ........................... 32 15:     *NoFragmentation: ...................... TRUE 16:     PrimaryAddressResolutionStatus: ........ 0 17:     ProtocolAddress: ....................... 16.174.12.1 18:     ProtocolAddressResolved: ............... NET-DPEP6400A.Emea.LissWare.Net 19:     *RecordRoute: .......................... 3 20:     ReplyInconsistency: .................... FALSE 21:     ReplySize: ............................. 32 22:     *ResolveAddressNames: .................. TRUE 23:     ResponseTime: .......................... 44 24:     ResponseTimeToLive: .................... 125 25:     RouteRecord: ........................... 16.183.44.1 26:                                              16.183.16.1 27:                                              16.174.12.1 28:     RouteRecordResolved: ................... NET-DPEN6400A 29:                                              16.183.16.1 30:     NET-DPEP6400A.Emea.LissWare.Net 31:     *SourceRoute: .......................... 32:     *SourceRouteType: ...................... 0 33:     StatusCode: ............................ 0 34:     *Timeout: .............................. 4000 35:     TimeStampRecord: ....................... -1513502205 36:     TimeStampRecordAddress: ................ 16.183.44.1 37:     TimeStampRecordAddressResolved: ........ NET-DPEN6400A 38:     *TimestampRoute: ....................... 1 39:     *TimeToLive: ........................... 80 40:     *TypeofService: ........................ 80 41: 42:     WMIPING host '16.174.12.1' ended. 

The Win32_PingStatus class is only available from the Windows XP and Windows Server 2003 platforms. Therefore, it is possible to request a PING from one of these platforms to any other host on the network. Note that you can perform a WMI remote connection from any WMI-enabled system to a Windows XP or a Windows Server 2003 platform. From there the host targeted by the PING command can be any TCP/IP host. The key point is to instantiate the Win32_PingStatus class from a Windows XP or Windows Server 2003 platform. In this case, we obtain a PING command that is remotely executed—an interesting feature compared with the traditional PING command-line utility, which is, by default, executed locally.

The Win32_PingStatus class usage with an asynchronous event timer is shown in Sample 3.60. The command-line parameter definition and parsing sections are skipped, since they continue to use the same logic.

Sample 3.60: PINGing a system at regular time intervals (Part I)

start example

   1:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  13:    <runtime>  ..:  44:    </runtime>  45:  46:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DecodeWinSockAPIErrorsFunction.vbs" />  47:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DecodePINGStatusCodeFunction.vbs" />  48:  49:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertiesFunction.vbs" />  50:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertyFunction.vbs" />  51:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  52:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\PauseScript.vbs" />  53:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\SendAlertFunction.vbs" />  54:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\SendMessageExtendedFunction.vbs" />  55:  56:    <object prog id= "objWMILocator " reference= " true "/>  57:    <object prog Microsoft.XMLDom"  />  59:    <object prog  />  60:  61:    <script language="VBscript">  62:    <![CDATA[  ..:  66:    Const cComputerName = "LocalHost"  67:    Const cWMINameSpace = "Root/cimv2"  68:    Const cWMITimerClass = "_IntervalTimerInstruction"  69:    Const cPINGTimerID = "MyPINGTimerEvent"  70:    Const cWMIPINGEventQuery = "Select * From __TimerEvent Where TimerID='MyPINGTimerEvent'"  71:    Const cWMIPingStatusClass = "Win32_PingStatus"  72:  73:    Const cTargetRecipient = "Alain.Lissoir@LissWare.Net"  74:    Const cSourceRecipient = "WMISystem@LissWare.Net"  75:  76:    Const cXSLFile = "PathLevel0Win32_PingStatus.XSL"  77:  78:    Const cSMTPServer = "relay.LissWare.Net"  79:    Const cSMTPPort = 25  80:    Const cSMTPAccountName = ""  81:    Const cSMTPSendEmailAddress = ""  82:    Const cSMTPAuthenticate = 0' 0=Anonymous, 1=Basic, 2=NTLM  83:    Const cSMTPUserName = ""  84:    Const cSMTPPassword = ""  85:    Const cSMTPSSL = False  86:    Const cSMTPSendUsing = 2            ' 1=Pickup, 2=Port, 3=Exchange WebDAV ...: 115:    ' ----------------------------------------------------------------------------------- 116:    ' Parse the command line parameters 117:    If WScript.Arguments.UnNamed.Count <> 1 Then 118:       WScript.Arguments.ShowUsage() 119:       WScript.Quit 120:    End If 121: 122:    strHost = WScript.Arguments.Unnamed.Item(0) 123:    If Len(strHost) = 0 Then 124:       WScript.Echo "Missing host address!" 125:       WScript.Arguments.ShowUsage() 126:       WScript.Quit 127:    End If 128: 129:    boolResolveAddressNames = WScript.Arguments.Named("a") 130:    If Len (boolResolveAddressNames) = 0 Then boolResolveAddressNames = False 131: ...: 177:    strComputerName = WScript.Arguments.Named("Machine") 178:    If Len(strComputerName) = 0 Then strComputerName = cComputerName 179: 180:    Set objWMISink = WScript.CreateObject ("WbemScripting.SWbemSink", "SINK_") 181: 182:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 183:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 184: 185:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _ 186:                                                     strUserID, strPassword) ...: 189:    ' ------------------------------------------------------------------------------------- 190:    Set objWMIClass = objWMIServices.Get (cWMITimerClass) 191: 192:    Set objWMIInstance = objWMIClass.SpawnInstance_ 193:    objWMIInstance.TimerID = cPINGTimerID 194:    objWMIInstance.IntervalBetweenEvents = intInterval * 1000 195:    objWMIInstance.Put_ (wbemChangeFlagCreateOrUpdate Or wbemFlagReturnWhenComplete) 196:    If Err.Number Then ErrorHandler (Err) 197: 198:    WScript.Echo "PING timer created." 199: 200:    ' ------------------------------------------------------------------------------------- 201:    objWMIServices.ExecNotificationQueryAsync objWMISink, cWMIPINGEventQuery 202:    If Err.Number Then ErrorHandler (Err) 203: 204:    WScript.Echo "Waiting for events..." 205: 206:    PauseScript "Click on 'Ok' to terminate the script ..." 207: 208:    WScript.Echo vbCRLF & "Cancelling event subscription ..." 209:    objWMISink.Cancel 210: 211:    ' ------------------------------------------------------------------------------------- 212:    objWMIInstance.Delete_ 213:    If Err.Number Then ErrorHandler (Err) 214: 215:    WScript.Echo "PING timer deleted." 216: 217:    Set objWMIServices = Nothing 218:    Set objWMISink = Nothing 219: 220:    WScript.Echo "Finished." 221: ...: ...: ...: 

end example

Once the WMI connection is established (lines 182 through 186), the script creates an interval timer instance (lines 190 through 198). During the command-line parameters parsing, the default interval is set to ten seconds if it is not specified. Next, the script submits the WQL event query (line 201) and enters an idle state while waiting for events (line 206).

When the script is stopped, the event subscription is canceled (lines 208 and 209), and the timer interval event is deleted (lines 212 and 213).

Sample 3.61: PINGing a system at regular time intervals (Part II)

start example

 ...: ...: ...: 221: 222:    ' ----------------------------------------------------------------------------------------- 223:    Sub SINK_OnObjectReady (objWbemObject, objWbemAsyncContext) ...: 229:        Wscript.Echo 230:        WScript.Echo FormatDateTime(Date, vbLongDate) & " at " & _ 231:                     FormatDateTime(Time, vbLongTime) & "." & vbCRLF & _ 232:                     " WMIPING host '" & strHost & "' started ..." 233: 234:        ' -- PING ----------------------------------------------------------------------------- 235:        Set objWMIInstance = objWMIServices.Get _ 236:                     (cWMIPingStatusClass & ".Address='" & strHost & "'," & _ 237:                     "ResolveAddressNames=" & boolResolveAddressNames & "," & _ 238:                     "BufferSize=" & intBufferSize & "," & _ 239:                     "NoFragmentation=" & boolNoFragmentation & "," & _ 240:                     "TimeToLive=" & intTimeToLive & "," & _ 241:                     "TypeofService=" & intTypeofService & "," & _ 242:                     "RecordRoute=" & intRecordRoute & "," & _ 243:                     "TimestampRoute=" & intTimestampRoute & "," & _ 244:                     "SourceRoute='" & strSourceRoute & "'," & _ 245:                     "SourceRouteType=" & intSourceRouteType & "," & _ 246:                     "Timeout=" & intTimeout) ...: 249:      If objWMIInstance.PrimaryAddressResolutionStatus Then 250:         WScript.Echo Space (2) & _ 251:                 DecodeWinSockAPIErrors (objWMIInstance.PrimaryAddressResolutionStatus) 252:                 If boolHasFailed = False And boolSendAlert Then 253:                    SendAlert objWMIInstance, _ 254:                     "WMIPing failed: " & _ 255:                     "From " & objWMIInstance.SystemProperties_.Item("__SERVER") & " '" & _ 256:                     DecodeWinSockAPIErrors(objWMIInstance.PrimaryAddressResolutionStatus) &_ 257:                     & "' - " & FormatDateTime(Date, vbLongDate) & _ 258:                     " at " & _ 259:                     FormatDateTime(Time, vbLongTime) 260:                     boolHasFailed = True 261:                  End If 262:       Else 263:          If objWMIInstance.StatusCode Then 264:             WScript.Echo Space (2) & _ 265:                     DecodePINGStatusCode (objWMIInstance.StatusCode) 266:             If boolHasFailed = False And boolSendAlert Then 267:                SendAlert objWMIInstance, _ 268:                 "WMIPing failed: " & _ 269:                 "From " & objWMIInstance.SystemProperties_.Item("__SERVER") & " '" & _ 270:                 DecodePINGStatusCode (objWMIInstance.StatusCode) & "' - " & _ 271:                 FormatDateTime(Date, vbLongDate) & _ 272:                 " at " & _ 273:                 FormatDateTime(Time, vbLongTime) 274:                 boolHasFailed = True 275:              End If 276:           Else 277:              WScript.Echo " Host '" & strHost & "' successfully contacted." 278:              boolHasFailed = False 279:           End If 280:        End If 281: 282:        If boolVerbose Then 283:           DisplayFormattedProperties objWMIInstance, 2 284:           WScript.Echo 285:        End If ...: 289:        WScript.Echo " WMIPING host '" & strHost & "' ended." 290: 291:    End Sub 292: 293:    ]]> 294:    </script> 295:  </job> 296:</package> 

end example

When the timer event notification occurs, the event sink routine is invoked (lines 223 through 291). Based on the parameters given on the command line (or the default parameters established during the command line parsing operation), the script gets a Win32_PingStatus instance (lines 235 through 246). The properties of this instance reflect the results of the PING command-line utility, which is displayed at line 283 if the verbose mode is requested.

If the PING naming resolution (line 249) or the PING status (line 263) failed, the script displays an error message (lines 250 and 251 or lines 264 and 265) and sends an email alert by reusing the SendAlert() function previously developed (lines 253 through 260 or lines 267 through 273). It is important to note that the script sends the email alert only one time. This is why a Boolean value is set to true once the alert has been sent (line 260 or 274). The next time the PING echo is successful, the Boolean value is reset to False (line 278).

3.7.2 Network Diagnostic provider

The Network Diagnostic provider exposes methods to test the IP connectivity to a particular host with eventually a specific port IP number. The provider is implemented as an instance and method provider, as shown in Table 3.59.

Table 3.59: The Network Diagnostic Providers Capabilities

Provider Name

Provider Namespace

Class Provider

Instance Provider

Method Provider

Property Provider

Event Provider

Event Consumer Provider

Support Get

Support Put

Support Enumeration

Support Delete

Windows Server 2003

Windows XP

Windows 2000 Server

Windows 2000 Professional

Windows NT 4.0

Network Diagnostic Provider

NetDiagProv

Root/CIMV2

X

X

X

X

X

X

X

This provider only supports one single class called NetDiagnostics, which is a singleton class. Available in the Windows XP release, this class has been removed from the Windows Server 2003 platform during the beta program. This class also exposes information about the proxy settings, such as the Win32_Proxy class. Since the Win32_Proxy class is especially designed to manage the proxy settings, it is the recommended class to work with. However, the NetDiagnostics class is quite interesting to use to test the TCP/IP port connectivity between two hosts. This is the purpose of Sample 3.62. This script sample is quite easy to use.

Sample 3.62: Testing connectivity with the Network Diagnostic provider

start example

   1:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime>  ..:  25:    </runtime>  26:  27:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\ReplaceStringFunction.vbs" />  28:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  29:  30:    <object prog  reference="true"/>  31:  32:    <script language="VBScript">  33:    <![CDATA[  ..:  37:    Const cComputerName = "LocalHost"  38:    Const cWMINameSpace = "Root\CIMv2"  39:    Const cWMIClass = "NetDiagnostics"  ..:  59:   ' ------------------------------------------------------------------------------------------  60:    Parse the command line parameters  61:    If WScript.Arguments.Named.Count = 0 Then  62:       WScript.Arguments.ShowUsage()  63:       WScript.Quit  64:    End If  ..:  89:    strComputerName = WScript.Arguments.Named("Machine")  90:    If Len(strComputerName) = 0 Then strComputerName = cComputerName  91:  92:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault  93:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate  94:  95:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _  96:                                                     strUserID, strPassword)  ..:  99:    Set objWMIInstance = objWMIServices.Get (cWMIClass & "=@") ...: 102:    If boolPing Then 103:       If intPingPort <> -1 Then 104:          boolRC = objWMIInstance.ConnectToPort (strPingAddress, intPingPort, strMessageOut) 105:          varTemp = "PINGing address '" & strPingAddress & ":" & intPingPort & "'" 106:       Else 107:          boolRC = objWMIInstance.Ping (strPingAddress, strMessageOut) 108:          varTemp = "PINGing address '" & strPingAddress & "'" 109:       End If 110: 111:       If boolRC Then 112:          WScript.Echo varTemp & " is successful." 113:       Else 114:          WScript.Echo varTemp & " has failed." 115:       End If 116: 117:       If Len (strMessageOut) Then 118:          ReplaceString StrMessageOut, "<br>", vbCRLF 119:          WScript.Echo vbCRLF & "Message:" & vbCRLF & vbCRLF & StrMessageOut 120:       End If 121:    End If 127:    ]]> 128:    </script> 129:  </job> 130: </package> 

end example

 C:\>WMINetDiag.wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMINetDiag.wsf [/PingAddress:value] [/PingPort:value]                       [/Machine:value] [/User:value] [/Password:value] Options: PingAddress : IP or host name to connect to. PingPort    : Port number to connect to. Machine     : Determine the WMI system to connect to. (default=LocalHost) User        : Determine the UserID to perform the remote connection. (default=none) Password    : Determine the password to perform the remote connection. (default=none) Examples:       WMINetDiag /PingAddress:proxy.LissWare.Net       WMINetDiag /PingAddress:proxy.LissWare.Net /PingPort:8080 

Sample 3.62 shows how to script with this NetDiagnostics class.

Once the command line is parsed (lines 60 through 90) and the WMI connectivity is established (lines 92 through 96), the script retrieves the singleton instance of the NetDiagnostics class (line 99). If the /PingAddress switch is given, a ping to the given IP address is executed with the Ping method (lines 107 and 108). If the ping is successful, the following output message is returned:

 C:\>WMINetDiag /PingAddress:proxy.LissWare.Net Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. PINGing address 'proxy.LissWare.Net' is successful. Message: pinging (proxy.LissWare.Net) 64 bytes from 10.10.10.254: icmp_seq = 0. time: 380 ms 64 bytes from 10.10.10.254: icmp_seq = 1. time: 421 ms 64 bytes from 10.10.10.254: icmp_seq = 2. time: 400 ms 64 bytes from 10.10.10.254: icmp_seq = 3. time: 401 ms 

Basically, this method performs the same task as the Win32_PingStatus class. However, none of the parameters to ping a host exposed by the Win32_PingStatus class is available from the NetDiagnostics class, which makes the Win32_PingStatus class more suitable to use. The message returned from the Ping method (line 107) contains an HTML carriage return <BR>; the message is parsed at line 118 with the ReplaceString() function included at line 27. Every occurrence of the <BR> HTML tag will be replaced with a carriage return and a line feed (line 118).

If the /PingPort switch is given, the ConnectToPort method is executed (line 104). Instead of performing a simple ping, the method tries to establish a connection with the given host at the specified port number. The obtained output is the following:

 C:\>WMINetDiag /PingAddress:proxy.LissWare.Net /PingPort:8080 Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. PINGing address 'proxy.LissWare.Net:8080' is successful. 

The method return code is tested to determine if there is an execution failure (line 111) and an appropriate message (built at line 105 or 108) is displayed (lines 112 through 114).

 C:\>WMINetDiag /PingAddress:proxy.LissWare.Net /PingPort:8081 Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. PINGing address 'proxy.LissWare.Net:8081'  has failed. 

3.7.3 IP routing provider

The IP routing providers give access to the IP version 4.0 routing table. They allow the examination and the modification of the IP routing table of a particular system. There are two IP routing providers: one instance provider, which gives access to the routing table information (called RouteProvider), and one event provider (called RouteEventProvider) able to trigger WMI events in case of modification of the routing table (see Table 3.60).

Table 3.60: The IP routing providers capabilities

Provider Name

Provider Namespace

Class Provider

Instance Provider

Method Provider

Property Provider

Event Provider

Event Consumer Provider

Support Get

Support Put

Support Enumeration

Support Delete

Windows Server 2003

Windows XP

Windows 2000 Server

Windows 2000 Professional

Windows NT 4.0

IP Route Provider

RouteEventProvider

Root/CIMV2

X

X

X

RouteProvider

Root/CIMV2

X

X

X

X

X

X

X

These providers are available in the Root\CIMv2 namespace and support the classes listed in Table 3.61.

Table 3.61: The IP routing Providers Classes

Name

Type

Comments

Win32_IP4RouteTable

Dynamic

The IP4RouteTable class information governs where network data packets are routed (e.g., usually Internet packets are sent to a gateway, and local packets may be routed directly by the client's machine). Administrators can use this information to trace problems associated with misrouted packets, and also direct a computer to a new gateway as necessary. This class deals specifically with IP4 and does not address IPX or IP6. It is only intended to model the information revealed when typing the 'Route Print' command from the command prompt.

Win32_IP4PersistedRouteTable

Dynamic

The IP4PersistedRouteTable class contains IP routes that are persisted. By default, the routes you add to the routing table aren't permanent. You lose these routes when you reboot your computer. However, if you use the command route - p add, Windows NT makes them permanent, so you won't lose the route when you reboot your computer. Persistent entries are automatically reinserted in your route table each time your computer's route table is rebuilt. Windows NT stores persistent routes in the Registry. This class deals specifically with IP4 and does not address IPX or IP6.

Win32_ActiveRoute

Association

The ActiveRoute class assoctiates the current IP4 Route being used with the persisted IP route table.

Win32_IP4RouteTableEvent

Event (Extrinsic)

The Win32_IP4RouteTableEvent class represents IP route change events resulting from the addition, removal, or modification of IP routes on the computer system.

Three classes work with the instance provider and one with the event provider. The Win32_IP4RouteTableEvent is an extrinsic class, which only provides timestamp information when an IP routing table modification occurs. To subscribe to this type of event, the following WQL event query must be used:

 Select * From Win32_IP4RouteTableEvent 

Once executed, the event returns the following information:

  1:   C:\GenericEventAsyncConsumer.wsf "Select * From Win32_IP4RouteTableEvent'  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:   Waiting for events...  6:  7:   BEGIN - OnObjectReady.  8:   Saturday, 15 December, 2001 at 13:41:29:  Win32_IP4RouteTableEvent  has been triggered.  9: 10:     - Win32_IP4RouteTableEvent ----------------------------------------------------- 11:     TIME CREATED: .......................... 15-12-2001 12:41:29 (20011215124129.409259+060) 12: 13:   END - OnObjectReady. 

The routing table is a collection of instances from the Win32_ IP4RouteTable class. However, each time a route is a persistent route, an association exists with the Win32_IP4PersistedRouteTable class. The association class used to link these two classes together is the Win32_ActiveRoute class (see Figure 3.35).

click to expand
Figure 3.35: The Win32_IP4RouteTable association.

We will take advantage of this association to determine if a route is a persistent route or to create a new persistent route. The purpose of Samples 3.63 through 3.65 is to illustrate the scripting logic to use to view, add, and delete IP routes (persistent routes or not).

Sample 3.63: Viewing, adding, and deleting IP v4.0 routes (Part I)

start example

   1: <?xml version="1.0"?>   .:   8: <package>   9:   <job>  ..:  13:     <runtime>  ..:  32:     </runtime>  33:  34:  35:     <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DecodeIPRouteFunction.vbs" />  36:     <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  37:  38:     <object prog  reference="true"/>  39:     <object prog  reference="true"/>  40:  41:     <script language="VBscript">  42:     <![CDATA[  ..:  46:     Const cComputerName = "LocalHost"  47:     Const cWMINameSpace = "Root/cimv2"  48:     Const cWMIIP4RouteClass = "Win32_IP4RouteTable"  49:     Const cWMIIPPersistedRouteClass = "Win32_IP4PersistedRouteTable"  50:     Const cWMIActiveRouteClass = "Win32_ActiveRoute"  51:  52:    Const cNotFound = &h80041002 ...: 159:    strComputerName = WScript.Arguments.Named("Machine") 160:    If Len(strComputerName) = 0 Then strComputerName = cComputerName 161: 162:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 163:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 164: 165:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _ 166:                                                     strUserID, strPassword) ...: 169:    ' -- PRINT --------------------------------------------------------------------------- 170:    If boolPrint = True Then 171:       Set objWMIIP4RouteInstances = objWMIServices.InstancesOf (cWMIIP4RouteClass) 172: 173:       WScript.Echo "ACTIVE ROUTES "  & String (84, "=") & vbCRLF 174:       WScript.Echo "    Destination            Mask        NextHop" & _ 175:                    "    Metric  IfNumber  Protocol      Type  Persistent" 176:       WScript.Echo String (98, "-") 177: 178:       For Each objWMIIP4RouteInstance In objWMIIP4RouteInstances 179:           strIPProtocol = DecodeIPProtocolCode (objWMIIP4RouteInstance.Protocol) 180:           strIP4RouteType = DecodeIPRouteType (objWMIIP4RouteInstance.Type) 181: 182:           Set objWMIPersistentInstances = objWMIServices.ExecQuery _ 183:                                               ("Associators of {" & _ 184:                                               objWMIIP4RouteInstance.Path_.RelPath & _ 185:                                               "} Where AssocClass=Win32_ActiveRoute") ...: 188:           If objWMIPersistentInstances.Count = 1 Then 189:              strPersistent = "         Y" 190:           Else 191:              strPersistent = "         -" 192:           End If ...: 196:           WScript.Echo String (15 - Len (objWMIIP4RouteInstance.Destination), " ") & _ 197:                        objWMIIP4RouteInstance.Destination & " " & _ 198:                        String (15 - Len (objWMIIP4RouteInstance.Mask), " ") & _ 199:                        objWMIIP4RouteInstance.Mask & _ 200:                        String (15 - Len (objWMIIP4RouteInstance.NextHop), " ") & _ 201:                        objWMIIP4RouteInstance.NextHop & _ 202:                        String (10 - Len (objWMIIP4RouteInstance.Metric1), " ") & _ 203:                        objWMIIP4RouteInstance.Metric1 & _ 204:                        String (10 - Len (objWMIIP4RouteInstance.InterfaceIndex), " ") & _ 205:                        objWMIIP4RouteInstance.InterfaceIndex & _ 206:                        String (10 - Len (strIPProtocol), " ") & _ 207:                        strIPProtocol & _ 208:                        String (10 - Len (strIP4RouteType), " ") & _ 209:                        strIP4RouteType & " " & _ 210:                        strPersistent 211:           Next 212: 213:           WScript.Echo vbCRLF & "Completed." ...: 216:    End If 217: ...: ...: ...: 

end example

The command-line parameters exposed by the script are as follows:

 C:\>WMIIP4Route.wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMIIP4Route.wsf Action Destination MASK Mask NextHop [METRIC Metric] [IF IfNumber]                        [/Persistent[+|-]] [/Machine:value] [/User:value] [/Password:value] Options: Action        : Specify the operation to perform: [Print] or [Add] or [Delete]. Destination   : IP network destination. MASK Mask     : Mask used by the specified IP network. NextHop       : IP address of the gateway to access the specified IP network. METRIC Metric : Specify the metric used. IF IfNumber   : Specify the Network Interface Number to use. Persistent    : Make the specified route persistent. Machine       : Determine the WMI system to connect to. (default=LocalHost) User          : Determine the UserID to perform the remote connection. (default=none) Password      : Determine the password to perform the remote connection. (default=none) Example:       WMIIP4Route.wsf PRINT       WMIIP4Route.wsf ADD 205.10.10.0 MASK 255.255.255.0 10.10.10.253 METRIC 30 IF 2       WMIIP4Route.wsf ADD 205.10.10.0 MASK 255.255.255.0 10.10.10.253 METRIC 30 IF 2 /Persistent+       WMIIP4Route.wsf DELETE 204.10.10.0 MASK 255.255.255.0 10.10.10.253 

First, you will note that the script accepts commands that are similar to the ROUTE.Exe command-line utility. This will make the user more familiar with the script usage. Before diving into the code, let's see what the output of the script PRINT command looks like.

 C:\>WMIIP4Route PRINT Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. ACTIVE ROUTES ====================================================================================     Destination           Mask        NextHop    Metric  IfNumber  Protocol     Type  Persistent ------------------------------------------------------------------------------------------------         0.0.0.0         0.0.0.0   10.10.10.254       30         2  Netmgmt  Indirect            -        10.0.0.0       255.0.0.0     10.10.10.3       30         2    Local    Direct            -      10.10.10.3 255.255.255.255      127.0.0.1       30         1    Local    Direct            -  10.255.255.255 255.255.255.255     10.10.10.3       30         2    Local    Direct            -       127.0.0.0       255.0.0.0      127.0.0.1        1         1    Local    Direct            -     192.10.10.0   255.255.255.0   10.10.10.253        1         2    10010  Indirect            Y     193.10.10.0   255.255.255.0   10.10.10.253        1         2    10010  Indirect            Y     194.10.10.0   255.255.255.0   10.10.10.253        1         2    10010  Indirect            Y     195.10.10.0   255.255.255.0   10.10.10.253        1         2    10010  Indirect            Y     200.10.10.0   255.255.255.0   10.10.10.253        1         2    10010  Indirect            Y     205.10.10.0   255.255.255.0   10.10.10.253       30         2  Netmgmt  Indirect            Y       224.0.0.0       240.0.0.0     10.10.10.3       30         2    Local    Direct            - 255.255.255.255 255.255.255.255     10.10.10.3        1         2    Local    Direct            - Completed. 

As you can see, the output is quite similar to the one obtained with the ROUTE.Exe PRINT command. Let's see how the code producing this output works by looking at the first part of the script shown in Sample 3.63. As usual, the lines defining and parsing the command-line parameters are skipped.

To print the routing table information, the basic principle is quite easy, since it consists of the retrieval of all instances available from the Win32_IP4RouteTable class (line 171). Next, the script enumerates in a loop all instances available (lines 178 through 211). Before displaying the properties of each IP route instance, the script checks if an association exists with an instance of the Win32_IP4PersistedRouteTable class (lines 182 through 192). If this is the case, it means that the examined IP route instance is a persistent route (line 189). The output is constructed in the loop (lines 196 through 210). Because some properties of Win32_IP4RouteTable class contain numbers having a particular meaning, the script includes the DecodeIPRouteFunction.vbs file (line 35), which contains several functions to decode the value of some properties (lines 179 and 180).

The Win32_IP4RouteTable class does not expose any method to add a new IP route. The creation of a new IP route is made by the creation of a new Win32_IP4RouteTable instance, as shown in Sample 3.64. However, the creation of the new instance is only made if there is no existing instance of the IP route to be added. This logic is implemented by trying first to retrieve an existing instance of the IP route to be added (lines 220 through 223). If the route exists, it will be updated with the new parameters. If the route does not exist (line 223), a new IP route will be created (lines 225 and 226). Next, independently of a route addition or update, the route parameters are set from line 234 through 240. Then the route is created or updated by using the Put_ method of the SWBemObject representing the IP route instance (lines 242 and 243).

Sample 3.64: Adding IP v4.0 routes (Part II)

start example

 ...: ...: ...: 217: 218:    ' -- Add ------------------------------------------------------------------------- 219:    If boolAdd = True Then 220:       Set objWMIIP4RouteInstance = objWMIServices.Get _ 221:                 (cWMIIP4RouteClass & ".Destination='" & strDestination & _ 222:                  "',NextHop='" & strNextHop & "'") 223:       If Err.Number = cNotFound Then 224:          Err.Clear 225:          Set objWMIClass = objWMIServices.Get (cWMIIP4RouteClass) 226:          Set objWMIIP4RouteInstance = objWMIClass.SpawnInstance_ 227:          If Err.Number Then 228:             ErrorHandler (Err) 229:          End If ...: 232:       End If 233: 234:       objWMIIP4RouteInstance.Destination = strDestination 235:       objWMIIP4RouteInstance.Mask = strMask 236:       objWMIIP4RouteInstance.NextHop = strNextHop 237:       objWMIIP4RouteInstance.Metric1 = intMetric 238:       objWMIIP4RouteInstance.InterfaceIndex = intIntNumber 239:       objWMIIP4RouteInstance.Protocol = intIPProtocol 240:       objWMIIP4RouteInstance.Type = intRouteType 241: 242:       objWMIIP4RouteInstance.Put_ (wbemChangeFlagCreateOrUpdate Or _ 243:                                    wbemFlagReturnWhenComplete) ...: 246:       If boolPersistent Then 247:          Set objWMIPersistentInstance = objWMIServices.Get _ 248:                    (cWMIIPPersistedRouteClass & _ 249:                    ".Destination='" & strDestination & _ 250:                    "',Mask='" & strMask & _ 251:                    "',Metric1='" & intMetric & _ 252:                    "',NextHop='" & strNextHop & "'") 253:          If Err.Number = cNotFound Then 254:             Err.Clear 255:             Set objWMIClass = objWMIServices.Get (cWMIIPPersistedRouteClass) 256:             Set objWMIPersistentInstance = objWMIClass.SpawnInstance_ ...: 262:          End If 263: 264:          objWMIPersistentInstance.Destination = strDestination 265:          objWMIPersistentInstance.Mask = strMask 266:          objWMIPersistentInstance.NextHop = strNextHop 267:          objWMIPersistentInstance.Metric1 = intMetric 268: 269:          objWMIPersistentInstance.Put_ (wbemChangeFlagCreateOrUpdate Or _ 270:                                         wbemFlagReturnWhenComplete) ...: 273:          Set objWMIAssocInstance = objWMIServices.Get _ 274:                    (cWMIActiveRouteClass & ".SameElement='" & _ 275:                    objWMIPersistentInstance.Path_.Path & _ 276:                    "',SystemElement='" & _ 277:                    objWMIIP4RouteInstance.Path_.Path & "'") 278:          If Err.Number = cNotFound Then 279:             Err.Clear 280:             Set objWMIClass = objWMIServices.Get (cWMIIPPersistedRouteClass) 281:             Set objWMIAssocInstance = objWMIClass.SpawnInstance_ ...: 288:             objWMIAssocInstance.SameElement = objWMIPersistentInstance.Path_.Path 289:             objWMIAssocInstance.SystemElement = objWMIIP4RouteInstance.Path_.Path 290: 291:             objWMIAssocInstance.Put_ (wbemChangeFlagCreateOrUpdate Or _ 292:                                       wbemFlagReturnWhenComplete) ...: 295:          End If ...: 300:          WScript.Echo "IP route " & strDestination & _ 301:                       " MASK " & strMask & " " & _ 302:                       strNextHop & " added as a persistent route." 303: 304:       Else 305:          WScript.Echo "IP route " & strDestination & _ 306:                       " MASK " & strMask & " " & _ 307:                       strNextHop & " added." 308:       End If ...: 311:    End If 312: ...: ...: ...: 

end example

Next, if the /Persistent+ switch is specified on the command line, the script creates the association that must be in place to make the route persistent (lines 247 through 303). Along these lines two instances are created, as follows:

  • One instance is made from the Win32_IP4PersistedRouteTable class (lines 247 through 270): The creation of this instance follows logic similar to the Win32_IP4RouteTable instance. The script checks first if no instance exists by trying to retrieve the instance (lines 247 through 252); if this operation fails (line 253), then a new instance is created (lines 255 and 256). Next, the instance properties are set (lines 264 through 267) and the information is saved in the CIM repository (lines 269 and 270).

  • One association instance is made from the Win32_ActiveRoute class (lines 273 through 292): Here, again, the instance logic creation is the same. The script verifies first if a Win32_ActiveRoute instance exists (lines 273 through 277) and if not, a new Win32_ActiveRoute instance is created (lines 280 and 281). To create or update the Win32_ActiveRoute association instance, the script reuses the WMI path of the two previous instances: the Win32_IP4RouteTable instance path (line 289) and the Win32_IP4PersistedRouteTable instance (line 288). Next, the information is committed into the CIM repository (lines 291 and 292).

The deletion of a Win32_IP4RouteTable instance is much easier. The logic is shown in Sample 3.65.

Sample 3.65: Deleting IP v4.0 routes (Part III)

start example

 ...: ...: ...: 312: 313:    ' -- DELETE ------------------------------------------------------------------------- 314:    If boolDelete = True Then 315:       Set objWMIIP4RouteInstance = objWMIServices.Get _ 316:                 (cWMIIP4RouteClass & ".Destination='" & strDestination & _ 317:                 "',NextHop='" & strNextHop & "'") ...: 320:       Set objWMIPersistentInstances = objWMIServices.ExecQuery _ 321:                                           ("Associators of {" & _ 322:                                           objWMIIP4RouteInstance.Path_.RelPath & _ 323:                                           "} Where AssocClass=Win32_ActiveRoute") ...: 326:       If objWMIPersistentInstances.Count = 1 Then 327:          Set objWMIPersistentInstance = objWMIServices.Get _ 328:                    (cWMIIPPersistedRouteClass & _ 329:                     ".Destination='" & objWMIIP4RouteInstance.Destination & _ 330:                     "',Mask='" & objWMIIP4RouteInstance.Mask & _ 331:                     "',Metric1='" & objWMIIP4RouteInstance.Metric1 & _ 332:                     "',NextHop='" & objWMIIP4RouteInstance.NextHop & "'") ...: 335:          objWMIPersistentInstance.Delete_ ...: 339:       End If ...: 343:       objWMIIP4RouteInstance.Delete_ ...: 346:       WScript.Echo "IP route " & strDestination & _ 347:                    " MASK " & strMask & " " & _ 348:                    strNextHop & " deleted." ...: 351:    End If ...: 355:    ]]> 356:    </script> 357:  </job> 358:</package> 

end example

First, the script retrieves the Win32_IP4RouteTable instance to delete (lines 315 through 317). Next, before executing the deletion of the retrieved instance, it is important to verify if there is an association with a Win32_IP4PersistedRouteTable instance. This verification is performed from line 320 through 326. If there is an association, the Win32_IP4PersistedRouteTable instance must also be retrieved (lines 327 through 332). Once all instances are retrieved, the script deletes each of them (lines 335 and 343). It is important to delete the associated instance, because, if a similar route is recreated, this route will be considered as a persistent route even if the /Persistent+ switch is not specified. The simple existence of a Win32_IP4PersistedRouteTable instance matching the Win32_IP4RouteTable information will make the route persistent.

3.7.4 DNS provider

The DNS provider supports the management of the DNS server, the DNS zones, and the DNS records. It is made up of one provider, which is both an instance provider and a method provider. Only available under Windows Server 2003 by default, the DNS provider was also available for Windows 2000 at ftp://ftp.microsoft.com/reskit/win2000/dnsprov.zip. With this provider it is possible to retrieve ("Get" and "Enumeration"), modify ("Put"), and delete ("Delete") DNS information. The provider capabilities are summarized in Table 3.62.

Table 3.62: The DNS Providers Capabilities

Provider Name

Provider Namespace

Class Provider

Instance Provider

Method Provider

Property Provider

Event Provider

Event Consumer Provider

Support Get

Support Put

Support Enumeration

Support Delete

Windows Server 2003

Windows XP

Windows 2000 Server

Windows 2000 Professional

Windows NT 4.0

DNS Provider

MS_NT_DNS_PROVIDER

Root/MicrosoftDNS

X

X

X

X

X

X

X

X

The DNS provider is available in the Root\MicrosoftDNS WMI namespace. It supports more than 30 classes, where most of them represent the various DNS records. Each DNS manageable component is represented with a corresponding WMI class, as shown in Table 3.63.

Table 3.63: The DNS Providers Classes

Name

Type

Comments

MicrosoftDNS_Cache

Dynamic

This class describes a cache existing on a DNS server. It shouldn't be confused with a Cache file which contains root hints. This class simplifies visualizing the containment of DNS objects, rather than representing a real object. The class, MicrosoftDNS_Cache, is a container for the resource records cached by the DNS server. Every instance of the class Micros oft DNS_Cache must be assigned to one and only one DNS server. It may be associated with (or more intuitively 'may contain') any number of instances of the classes, Micros oft DNS_Domain and/or Microsoft DNS_Resource Record.

MicrosoftDNS_Domain

Dynamic

This class represents a Domain in a DNS hierarchy tree.

MicrosoftDNS_Resource Record

Dynamic

This class represents the general properties of a DNS Resource Record.

MicrosoftDNS_RootHints

Dynamic

This class describes the Root Hints stored in a Cache file on a DNS server. This class simplifies visualizing the containment of DNS objects, rather than representing a real object. Class MicrosoftDNS_Root Hints is a container for the resource records stored by the DNS server in a Cache file. Every instance of the class MicrosoftDNS_RootHints must be assigned to one and only one DNS server. It may be associated with (or more intuitively 'may contain') any number of instances of class MicrosoftDNS Resource Record.

MicrosoftDNS_Server

Dynamic

This class describes a DNS server. Every instance of this class may be associated with (or more intuitively 'may contain') one instance of class Microsoft DNS_Cache, one instance of class MicrosoftDNS_RootHints and multiple instances of class MicrosoftDNS_Zone.

MicrosoftDNS_Statistic

Dynamic

A single DNS Server statistic.

MicrosoftDNS_Zone

Dynamic

This class describes a DNS Zone. Every instance of the class MicrosoftDNS_Zone must be assigned to one and only one DNS server. Zones may be associated with (or more intuitively 'may contain') any number of instances of the classes MicrosoftDNS_Domain and/or Microsoft DNS_Resource Record.

MicrosoftDNS_DomainDomainContainment

Association

Domains may contain other Domains. (Every instance of the Microsoft DNS_Domain class may contain multiple other instances of Microsoft DNS_Domain.) An instance of a MicrosoftDNS_Domain object is directly contained in (at most) one higher-level MicrosoftDNS_Domain.

MicrosoftDNS_DomainResourceRecordContainment

Association

Every instance of the class MicrosoftDNS_Domain may contain multiple instances of the class, MicrosoftDNS_ResourceRecord. Every instance of the class MicrosoftDNS_ResourceRecord belongs to a single instance of the class MicrosoftDNS_Domain and is defined to be weak to that instance.

MicrosoftDNS_ServerDomainContainment

Association

Every instance of the class MicrosoftDNS_Server may contain multiple instances of the class Microsoft DNS_Domain. Every instance of the class Microsoft DNS_Domain belongs to a single instance of the class Microsoft DNS_Server and is defined to be weak to that server.

MicrosoftDNS_AAAAType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type AAAA record.

MicrosoftDNS_AFSDBType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type AFSDB record.

MicrosoftDNS_ATMAType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type ATMA record.

MicrosoftDNS_AType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type A record.

MicrosoftDNS_CNAMEType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type CNAME record.

MicrosoftDNS_HINFOType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type HINFO record.

MicrosoftDNS_ISDNType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type ISDN record.

MicrosoftDNS_KEYType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type KEY record.

MicrosoftDNS_MBType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type MB record.

MicrosoftDNS_MDType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type MD record.

MicrosoftDNS_MFType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type MF record.

MicrosoftDNS_MOType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type MG record.

MicrosoftDNS_MINFOType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type MINFO record.

MicrosoftDNS_MRType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type MR record.

MicrosoftDNS_MXType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type MX record.

MicrosoftDNS_NSType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type NS record.

MicrosoftDNS_NXTType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type NXT record.

MicrosoftDNS_PTRType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type PRT record.

MicrosoftDNS_RPType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type RPT record.

MicrosoftDNS_RTType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type RTT record.

MicrosoftDNS_SIGType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type SIG record.

MicrosoftDNS_SOAType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type SOA record.

MicrosoftDNS_SRVType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type SRVrecord.

MicrosoftDNS_TXTType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type TXT record.

MicrosoftDNS_WINSRType

Dynamic

A subclass of MicrosoftDNS Resource Record that represents a Type WINSR record.

MicrosoftDNS_WINSType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type WINS C12record.

MicrosoftDNS_WKSType

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type WKS record.

MicrosoftDNS_X25Type

Dynamic

A subclass of MicrosoftDNS_ResourceRecord that represents a Type X25 record.

It is important to note that the DNS provider is not implemented as a WMI event provider, which forces you to use the WITHIN statement in a WQL event query. For example, to monitor the A record modifications made in the LissWare.Net domain, the following WQL event query would be used:

 Select * From_InstanceCreationEvent Within 10 Where TargetInstance ISA  'MicrosoftDNS_AType'                                         And TargetInstance.DomainName='LissWare.Net' 

When modifying an existing record, it is important to note that no __InstanceModificationEvent intrinsic event is returned. A DNS record update corresponds to a DNS record deletion followed by a DNS record creation. This is the reason why the WQL event query sample uses the __InstanceCreationEvent intrinsic event class instead of the __InstanceModificationEvent intrinsic event class.

Because there is no direct relationship between the DNS server host name and the domain definitions that it could contain, the DNS CIM representation defines an association class called MicrosoftDNS_ServerDomainContainment to associate the MicrosoftDNS_Server and the MicrosoftDNS_ Domain classes, as shown in Figure 3.36.

click to expand
Figure 3.36: The DNS server class is associated with the DNS domain class.

In the same way, because a DNS domain may contain another DNS domain, an association class called MicrosoftDNS_DomainDomainContainment establishes the relationship with the MicrosoftDNS_Domain class itself, as shown in Figure 3.37. The MicrosoftDNS_Domain is a superclass used for the definition of three subclasses called the MicrosoftDNS_RootHints class, the MicrosoftDNS_Cache class, and the MicrosoftDNS_Zone. It is interesting to note that a DNS domain delegation will be represented as an association of two MicrosoftDNS_Domain instances.

click to expand
Figure 3.37: The DNS domain class is associated with itself.

Last but not least, because a DNS domain usually contains DNS records, an association class called MicrosoftDNS_DomainResourceRecordContainment establishes the relationship between the MicrosoftDNS_ Domain superclass and the MicrosoftDNS_ResourceRecord superclass, as shown in Figure 3.38.

click to expand
Figure 3.38: The DNS domain class is associated with the DNS records superclass.

The MicrosoftDNS_ResourceRecord class is used as a superclass because it is used as a parent class for all record-specific classes listed in Table 3.63.

These associations can be exploited to retrieve items contained in various DNS containers. For example, to retrieve the list of domains hosted in a DNS server called NET-DPEN6400A in the LissWare.Net domain, we will use the following WQL data query:

 Associators of {MicrosoftDNS_Server.Name="net-dpen6400a.LissWare.Net"} Where                AssocClass=MicrosoftDNS_ServerDomainContainment 

The MicrosoftDNS_Server class is using only one key property, which is the Fully Qualified Domain Name (FQDN) of the DNS server. Thus, the WQL query only requires the name of the server for the selection.

In the same way, to retrieve the list of records that exist in a zone called LissWare.Net hosted in a server called NET-DPEN6400A, which is part of the LissWare.Net domain, the following WQL data query will be used:

 Associators of {MicrosoftDNS_Zone.ContainerName="LissWare.Net",                 DnsServerName="net-dpen6400a.LissWare.Net",                 Name="LissWare.Net"} Where             AssocClass=MicrosoftDNS_DomainResourceRecordContainment 

Because the MicrosoftDNS_Zone has three key properties, the WQL query specifies the three key properties for the selection. This makes the WQL query quite complex to formulate in order to retrieve the DNS record list for a specific zone. Because the MicrosoftDNS_ResourceRecord class exposes a property that contains the container name, which is the domain name, it is possible to use the following WQL query instead:

 Select * From MicrosoftDNS_ResourceRecord Where ContainerName='LissWare.Net' 

Of course, in this case we do not exploit the associations in place. However, we use the fact that the MicrosoftDNS_ResourceRecord class is a superclass to simplify the WQL query.

The next script sample, shown in Samples 3.66 through 3.69, utilizes the DNS provider capabilities to manage the DNS server, the DNS zones, and DNS records from the command-line. It also exploits some of the characteristics we have seen regarding the DNS association classes. Due to the huge number of configurable parameters exposed by the DNS classes, the command-line parameters syntax is especially adapted. For example, to create an Active Directory integrated zone, the command would be as follows:

 C:\>WMIDNS.Wsf Zone Create Name=LissWare.Net ZType=ADIntegrated                            AdminEmailName=Administrator@LissWare.Net Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Zone  LissWare.Net  created. 

Once the zone is created, it is possible to create some records—for example, an A record. In this case, the command line would be as follows:

 C:\>WMIDNS.Wsf Record Create RType=A DomainName=LissWare.Net Host=Net-dpen6400a                              Class=IN TTL=3600 HostAddress=10.10.10.7 Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. A' record for 'Net-dpen6400a.LissWare.Net' created. 

And to create a DNS alias for the previously created A record, the command would be as follows:

 C:\>WMIDNS.Wsf Record Create RType=CNAME DomainName=LissWare.Net Host=www                              Class=IN TTL=7200 HostAddress=Net-dpen6400a.LissWare.Net Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. CNAME  record for 'www.LissWare.Net' created. 

The following is a complete list of command-line parameters supported by the next sample script.

 C:\>WMIDNS.Wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMIDNS.wsf DNS component [SERVER View] [SERVER Start] [SERVER Stop] [SERVER Scavenging]                                 [ZONE View] [ZONE Create] [ZONE Update] [ZONE AgeAllRecords]                                 [ZONE Refresh] [ZONE Pause] [ZONE Reload] Options: DNS component               : Select the DNS item to customize. Can be [Server],                               [Zone], [Cache], [RootHints], [Record] SERVER View                 : Views the DNS Server properties. SERVER Start                : Starts the DNS Service. SERVER Stop                 : Stops the DNS Service. SERVER Scavenging           : Scavenging of stale records in the zones subjected to scavenging. SERVER BootMethod           : Defines the boot method. Only [File], [Registry] or [AD] is accepted. SERVER EventLogLevel        : Defines the logging level. Only [None], [Errors],                               [ErrorsAndWarnings] or [All] is accepted. SERVER Forwarders           : Defines the IP address list used as fowarders. SERVER IsSlave                     : Defines if the DNS server acts as a slave server.                               Only [True] or [False] is accepted. SERVER NoRecursion          : Defines the recursion usage. Only [Disable] or [Enable] is accepted. SERVER RoundRobin           : Define the round robin usage. Only [True] or [False] is accepted. SERVER ListenAddresses      : Define the IP address used to listen DNS requests. ZONE View                   : Views the Zone properties. ZONE Create                 : Creates a DNS new zone. ZONE Update                 : Updates an existing DNS zone. ZONE AgeAllRecords          : Enables aging for some or all non-NS and non-SOA records in a zone. ZONE Refresh                : Forces the DNS server to check the master server of a secondary                               zone for updates. ZONE Pause                  : Pauses the zone. ZONE Reload                 : Reloads the zone. ZONE ResetSecondaries       : Resets the secondary IP addresses. ZONE Resume                 : Resumes the zone. ZONE UpdateFromDS           : Forces an update of the zone from the DS. This method is                               only valid for DS-integrated zones. ZONE WriteBackZone          : Saves the zone's data to persistent storage. ZONE Delete                 : Deletes a zone    Name                     : Name of the zone to manage.    ZType                    : Zone type. Can be [ADIntegrated], [Primary], [Secondary] or [Stub]    DataFile                 : Zone file containing the zone data.    AdminEmailName           : Zone administrator email address.    IPAddresses              : Secondary DNS servers IP addresses.    SecondaryServers         : IP addresses of the secondary servers.    SecureSecondaries        : Secondary DNS zone transfer mode. Only [AnyServers], [OnlyNSServers],                               [OnlyListedServers] or [None] is accepted.    NotifyServers            : IP addresses of the secondary servers to notify.    Notify                   : Notify mode. Only [OnlyNSServers], [OnlyListedServers]                               or [None] is accepted. CACHE Clear                 : Clears the DNS cache. ROOTHINTS WriteBackDataFile : Saves the RootHints' zone data to persistent storage. RECORD View                 : View DNS records for a given zone. RECORD Create               : Create DNS records in a given zone. RECORD Delete               : Delete DNS records from a given zone.    RType                    : Record Type. Can be [A], [CNAME], [NS], ... or any record type supported.    DomainName               : Record's domain name    Host                     : Corresponding host to the record.    Class                    : Class of the record.    TTL                      : Time to Live of the record.    HostAddress              : HostAddress of the record (Could be an IP address or a host                               name based on the record type). Machine                     : determine the WMI system to connect to. (default=LocalHost) User                        : determine the UserID to perform the remote connection. (default=none) Password                    : determine the password to perform the remote                               connection. (default=none) Examples:       WMIDNS.Wsf Server View       WMIDNS.Wsf Server Start       WMIDNS.Wsf Server Stop       WMIDNS.Wsf Server Scavenging       WMIDNS.Wsf Server BootMethod=Registry       WMIDNS.Wsf Server EventLogLevel=ErrorsAndWarnings       WMIDNS.Wsf Server Forwarders=10.10.10.1,172.16.23.1       WMIDNS.Wsf Server IsSlave=True       WMIDNS.Wsf Server NoRecursion=Disabled       WMIDNS.Wsf Server RoundRobin=True       WMIDNS.Wsf Server ListenAddresses=10.10.10.3,10.10.10.4       WMIDNS.Wsf Server ListenAddresses=10.10.10.3 RoundRobin=True Forwarders=10.10.10.1                         BootMethod=Registry EventLogLevel=ErrorsAndWarnings       WMIDNS.Wsf Zone View       WMIDNS.Wsf Zone View Name=LissWare.Net       WMIDNS.Wsf Zone Create Name=LissWare.Net ZType=ADIntegrated                              AdminEmailName=Administrator@LissWare.Net       WMIDNS.Wsf Zone Create Name=LissWare.Net ZType=Primary DataFile=LissWare.Net.Dns                              AdminEmailName=Administrator@LissWare.Net       WMIDNS.Wsf Zone Create Name=LissWare.Net ZType=Secondary DataFile=LissWare.Net.Dns                              AdminEmailName=Administrator@LissWare.Net IPAddresses=10.10.10.3       WMIDNS.Wsf Zone Create Name=LissWare.Net ZType=Stub DataFile=LissWare.Net.Dns                              AdminEmailName=Administrator@LissWare.Net IPAddresses=10.10.10.3       WMIDNS.Wsf Zone Update Name=LissWare.Net ZType=ADIntegrated                              AdminEmailName=Administrator@LissWare.Net       WMIDNS.Wsf Zone Update Name=LissWare.Net ZType=Primary DataFile=LissWare.Net.Dns                              AdminEmailName=Administrator@LissWare.Net       WMIDNS.Wsf Zone Update Name=LissWare.Net ZType=Primary DataFile=LissWare.Net.Dns                              AdminEmailName=Administrator@LissWare.Net ZUpdate=NotAllowed       WMIDNS.Wsf Zone Update Name=LissWare.Net ZType=Secondary DataFile=LissWare.Net.Dns                              AdminEmailName=Administrator@LissWare.Net IPAddresses=10.10.10.3       WMIDNS.Wsf Zone Update Name=LissWare.Net ZUpdate=NotAllowed       WMIDNS.Wsf Zone Update Name=LissWare.Net ZUpdate=AllowUpdates       WMIDNS.Wsf Zone Update Name=LissWare.Net ZUpdate=AllowSecureUpdates       WMIDNS.Wsf Zone Refresh Name=LissWare.Net       WMIDNS.Wsf Zone Pause Name=LissWare.Net       WMIDNS.Wsf Zone Reload Name=LissWare.Net       WMIDNS.Wsf Zone ResetSecondaries Name=LissWare.Net SecondaryServers=10.10.10.4,10.10.10.5                                        SecureSecondaries=OnlyListedServers                                        NotifyServers=10.10.10.4,10.10.10.5 Notify=OnlyListedServers       WMIDNS.Wsf Zone Resume Name=LissWare.Net       WMIDNS.Wsf Zone UpdateFromDS Name=LissWare.Net       WMIDNS.Wsf Zone WriteBackZone Name=LissWare.Net       WMIDNS.Wsf Zone Delete Name=LissWare.Net       WMIDNS.Wsf Cache Clear       WMIDNS.Wsf RootHints WriteBackDataFile       WMIDNS.Wsf Record View RType=A DomainName=LissWare.Net       WMIDNS.Wsf Record Create RType=A DomainName=LissWare.Net Host=Net-dpen6400a Class=IN                                TTL=3600 HostAddress=10.10.10.7       WMIDNS.Wsf Record Create RType=CNAME DomainName=LissWare.Net Host=www Class=IN                                TTL=7200 HostAddress=Net-dpen6400a.LissWare.Net       WMIDNS.Wsf Record Delete RType=A DomainName=LissWare.Net Host=Net-dpen6400a Class=IN                                TTL=3600 HostAddress=10.10.10.7       WMIDNS.Wsf Record Delete RType=CNAME DomainName=LissWare.Net Host=www Class=IN                                TTL=7200 HostAddress=Net-dpen6400a.LissWare.Net. 

Note that Samples 3.66 through 3.69 make use of the most important parameters exposed by the DNS classes. To simplify the script coding and focus on the DNS class usage, the script performs a very limited syntax checking. However, if you require a stronger syntax checking and some properties supported by the DNS classes that are not currently implemented in Samples 3.66 through 3.69, the script is very easy to extend, since its logic is quite linear. Although a smarter scripting technique is possible to make the script smaller, this linear logic has the advantage of being easy to follow and understand, which is the primary purpose.

We can split Samples 3.66 through 3.69 into the following three parts:

  • A portion to manage the DNS server, shown in Sample 3.66

    Sample 3.66: Managing the DNS server (Part I)

    start example

       l:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime> ...: 108:    </runtime> 109: 110:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DecodeDNSFunction.vbs" /> 111:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertyFunction.vbs" /> 112: 113:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\ConvertStringInArrayFunction.vbs" /> 114:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" /> 115: 116:    <object prog  reference="true"/> 117:    <object prog VBscript"> 120:    <![CDATA[ ...: 124:    Const cComputerName = "LocalHost" 125:    Const cWMINameSpace = "Root/MicrosoftDNS" ...: 569:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 570:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 571: 572:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _ 573:                                                     strUserID, strPassword) ...: 576:    Set objWMIInstances = objWMIServices.InstancesOf ("MicrosoftDNS_Server") 577: 578:    If objWMIInstances.Count = 1 Then 579:       For Each objWMIInstance In objWMIInstances 580:           strDNSServerName = objWMIInstance.Name 581:       Next 582:    End If ...: 586:    '----------------------------------------------------------------------------------------- 587:    If boolSRWiew Then 588:       Set objWMIInstance = objWMIServices.Get ( "MicrosoftDNS_Server. Name='" & _ 589:                                                 strDNSServerName & "'") ...: 592:       WScript.Echo "- " & objWMIInstance.Name & " " & String (60, "-") 593:       Set objWMIPropertySet = objWMIInstance.Properties_ 594:       For Each objWMIProperty In objWMIPropertySet 595:           DisplayFormattedProperty objWMIInstance, _ 596:                                    "  " & objWMIProperty.Name, _ 597:                                    objWMIProperty.Name, _ 598:                                    Null 599:       Next ...: 602:       WScript.Echo 603: 604:       WScript.Echo "- Hosted zones " & String (60, "-") 605: 606:       Set objWMIAssocInstances = objWMIServices. ExecQuery _ 607:                                        ("Associators of { " & _ 608:                                        objWMIInstance.Path_.RelPath & _ 609:                                        "} Where AssocMicrosoftDNS_ServerDomainContainment") 611:       For Each objWMIAssocInstance In objWMIAssocInstances 612:           If objWMIAssocInstance.Path_. Class = "MicrosoftDNS_Zone" Then 613:              WScript.Echo "  " & objWMIAssocInstance .Name 614:           End If 615:       Next ...: 619:    End If 620:    If boolSRVStart Then 621:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Server.Name='" & _ 622:                                                strDNSServerName & "'") ...: 625:       objWMIInstance.StartService() ...: 628:       WScript.Echo "DNS Server started." 631:    End If 632:    If boolSRVStop Then 633:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Server.Name='" & _ 634:                                                strDNSServerName & "'") ... 637:       objWMIInstance.StopService() ...: 640:       WScript.Echo "DNS Server stopped." 643:    End If 644:    If boolSRVScavenging Then 645:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Server.Name='" & _ 646:                                                strDNSServerName & "'") ...: 648:       objWMIInstance.StartScavenging() ...: 650:       WScript.Echo "DNS Server Scavenging requested." ...: 652:    End If 653:    If boolBootMethod Then 654:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Server.Name='" & _ 655:                                                strDNSServerName & "'") ...: 658:       objWMIInstance.bootMethod = intBootMethod 659: 660:       objWMIInstance.Put_ (wbemChangeFlagUpdateOnly Or _ 661:                            wbemFlagReturnWhenComplete) ...: 664:       WScript.Echo "DNS Server boot method updated." ...: 667:    End If 668:    If boolEventLogLevel Then 669:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Server.Name='" & _ 670:                                                strDNSServerName & "'") ...: 673:       objWMIInstance.EventLogLevel = intEventLogLevel 674: 675:       objWMIInstance.Put_ (wbemChangeFlagUpdateOnly Or _ 676:                            wbemFlagReturnWhenComplete) ...: 679:       WScript.Echo "DNS Server event log level updated." ...: 682:    End If 683:    If boolForwarders Then 684:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Server.Name='" & _ 685:                                                strDNSServerName & "'") ...: 688:       objWMIInstance.Forwarders = arrayForwarders 689: 690:       objWMIInstance.Put_ (wbemChangeFlagUpdateOnly Or _ 691:                            wbemFlagReturnWhenComplete) ...: 694:       WScript.Echo "DNS Server fowarders updated." ...: 697:    End If 698:    If boolSlave Then 699:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Server.Name='" & _ 700:                                                strDNSServerName & "'") ...: 703:       objWMIInstance.IsSlave = boolIsSlave 704: 705:       objWMIInstance.Put_ (wbemChangeFlagUpdateOnly Or _ 706:                            wbemFlagReturnWhenComplete) ...: 709:       WScript.Echo "DNS Server slave updated." ...: 712:    End If 713:    If boolUpdateRecursion Then 714:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Server.Name='" & _ 715:                                                strDNSServerName & "'") ...: 718:       objWMIInstance.NoRecursion = boolRecursion 719: 720:       objWMIInstance.Put_ (wbemChangeFlagUpdateOnly Or _ 721:                            wbemFlagReturnWhenComplete) ...: 724:       WScript.Echo "DNS Server recursion updated." ...: 727:    End If 728:    If boolUpdateRoundRobin Then 729:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Server.Name='" & _ 730:                                                strDNSServerName & "'") ...: 733:       objWMIInstance.RoundRobin = boolRoundRobin 734: 735:       objWMIInstance.Put_ (wbemChangeFlagUpdateOnly Or _ 736:                            wbemFlagReturnWhenComplete) ...: 739:       WScript.Echo "DNS Server round robin updated." ...: 742:    End If 743:    If boolIPAddresses Then 744:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Server.Name='" & _ 745:                                                strDNSServerName & "'") ...: 748:       objWMIInstance.ListenAddresses = arrayIPAddresses 749: 750:       objWMIInstance.Put_ (wbemChangeFlagUpdateOnly Or _ 751:                            wbemFlagReturnWhenComplete) ...: 754:       WScript.Echo "DNS Server listen IP addresses updated." ...: 757:    End If 758: ...: ...: ...: 

    end example

  • A portion to manage the DNS zones, shown in Samples 3.67 and 3.68

    Sample 3.67: Viewing the DNS zones (Part IIa)

    start example

     ...: ...: ...: 758: 759:    ' ----------------------------------------------------------------------------------------- 760:    If boolZONEView Then 761:       If Len (strZoneName) Then 762:          Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Zone." & _ 763:                                     "ContainerName='" & strZoneName & _ 764:                                     "',DnsServerName='" & strDNSServerName & _ 765:                                     "',Name='" & strZoneName & "'") ...: 768:          WScript.Echo "- " & objWMIInstance.Name & " " & String (60, "-") 769:          Set objWMIPropertySet = objWMIInstance.Properties_ 770:          For Each objWMIProperty In objWMIPropertySet 771:              Select Case objWMIProperty.Name 772:                     Case "AllowUpdate" 773:                          DisplayFormattedProperty objWMIInstance, _ 774:                                 "  " & objWMIProperty.Name, _ 775:                                 DecodeZoneUpdate (objWMIProperty.Value), _ 776:                                 Null 777:                     Case "Notify" 778:                          DisplayFormattedProperty objWMIInstance, _ 779:                                 "  " & objWMIProperty.Name, _ 780:                                 DecodeZoneNotify (objWMIProperty.Value), _ 781:                                 Null 782:                     Case "SecureSecondaries" 783:                          DisplayFormattedProperty objWMIInstance, _ 784:                                 "  " & objWMIProperty.Name, _ 785:                                 DecodeZoneTransfer (objWMIProperty.Value), _ 786:                                 Null 787:                     Case "ZoneType" 788:                          DisplayFormattedProperty objWMIInstance, _ 789:                                 "  " & objWMIProperty.Name, _ 790:                                 DecodeZoneType (objWMIProperty.Value, _ 791:                                 objWMIInstance.DsIntegrated), _ 792:                                 Null 793:                     Case Else 794:                          DisplayFormattedProperty objWMIInstance, _ 795:                                 "  " & objWMIProperty.Name, _ 796:                                 objWMIProperty.Name, _ 797:                                 Null 798:              End Select 799:          Next ...: 802:          WScript.Echo 803:       Else 804:          Set objWMIInstances = objWMIServices.InstancesOf ("MicrosoftDNS_Zone") ...: 807:          WScript.Echo "                Zone Name           Type             Updates" & _ 808:                       "            Transfer         Notify list  Reverse Zone     Paused" 809:          WScript.Echo String (124, "-") 810:          For Each objWMIInstance In objWMIInstances 811:              strZoneType = DecodeZoneType (objWMIInstance.ZoneType, _ 812:                                            objWMIInstance.DsIntegrated) 813:              strZoneTransfer = DecodeZoneTransfer (objWMIInstance.SecureSecondaries) 814:              strZoneNotify = DecodeZoneNotify (objWMIInstance.Notify) 815:              strZoneUpdate = DecodeZoneUpdate (objWMIInstance.AllowUpdate) 816: 817:              WScript.Echo String (25 - Len (objWMIInstance.Name), " ") & _ 818:                           objWMIInstance.Name & _ 819:                           String (15 - Len (strZoneType), " ") & _ 820:                           strZoneType & _ 821:                           String (20 - Len (strZoneUpdate), " ") & _ 822:                           strZoneUpdate & _ 823:                           String (20 - Len (strZoneTransfer), " ") & _ 824:                           strZoneTransfer & _ 825:                           String (20 - Len (strZoneNotify), " ") & _ 826:                           strZoneNotify & _ 827:                           String (14 - Len (objWMIInstance.Reverse), " ") & _ 828:                           objWMIInstance.Reverse & _ 829:                           String (10 - Len (objWMIInstance.Paused), " ") & _ 830:                           objWMIInstance.Paused 831:          Next ...: 834:       End If 835:    End If ...: ...: ...: 

    end example

    Sample 3.68: Managing the DNS zones (Part IIb)

    start example

      ...:  ...:  ...:  835:    End If  836:    If boolZONECreate Then  837:       Set objWMIClass = objWMIServices.Get ("MicrosoftDNS_Zone")  ...:  840:       Select Case intZoneType  841:              Case 1  842:                   objWMIClass.CreateZone strZoneName, _  843:                                          0,  _  844:                                          True, , , strAdminEmailName  845:              Case 2  846:                   objWMIClass.CreateZone strZoneName, _  847:                                          0, _  848:                                          False,  849:                                          strZoneDataFile, _  850:                                          ,  _  851:                                          strAdminEmailName  852:              Case 3  853:                   objWMIClass.CreateZone strZoneName, _  854:                                          1, _  855:                                          False, _  856:                                          strZoneDataFile, _  857:                                          arrayIpAddresses, _  858:                                          strAdminEmailName  859:              Case 4  860:                   objWMIClass.CreateZone strZoneName, _  861:                                          2, _  862:                                          False, _  863:                                          strZoneDataFile, _  864:                                          arrayIpAddresses, _  865:                                          strAdminEmailName  866:       End Select  ...:  869:       WScript.Echo "Zone '" & strZoneName & "' created."  ...:  872:    End If  873:    If boolZONEChange Then  874:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Zone." & _  875:                                  "ContainerName='" & strZoneName & _  876:                                  "',DnsServerName='" & strDNSServerName & _  877:                                  "',Name='" & strZoneName & "'")  ...:  880:       Select Case intZoneType  881:              Case 1  882:                   objWMIInstance.ChangeZoneType 0, True, , , strAdminEmailName  883:              Case 2  884:                   objWMIInstance.ChangeZoneType 0, _  885:                                                 False, _  886:                                                 strZoneDataFile, _  887:                                                 , _  888:                                                 strAdminEmailName  889:              Case 3  890:                   objWMIInstance.ChangeZoneType 1, _  891:                                                 False, _  892:                                                 strZoneDataFile, _  893:                                                 arrayIpAddresses, _  894:                                                 strAdminEmailName  895:              Case 4  896:                   objWMIInstance.ChangeZoneType 2, _  897:                                                 False, _  898:                                                 strZoneDataFile, _  899:                                                 arrayIpAddresses, _  900:                                                 strAdminEmailName  901:       End Select  ...:  904:       objWMIInstance.AllowUpdate = intZoneUpdate  905:  906:       objWMIInstance.Put_ (wbemChangeFlagUpdateOnly Or _  907:                            wbemFlagReturnWhenComplete)  ...:  910:       WScript.Echo "Zone '" & strZoneName & "' updated."  ...:  913:    End If  914:    If boolZONEDelete Then  915:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Zone." & _  916:                                  "ContainerName='" & strZoneName & _  917:                                  "',DnsServerName='" & strDNSServerName & _  918:                                  "',Name='" & strZoneName & "'")  ...:  921:       objWMIInstance.Delete_  ...:  924:       WScript.Echo "Zone '" & strZoneName & "' deleted."  ...:  927:    End If  928:    If boolZONERefresh Then  929:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Zone." & _  930:                                  "ContainerName='" & strZoneName & _  931:                                  "',DnsServerName='" & strDNSServerName & _  932:                                  "',Name='" & strZoneName & "'")  ...:  935:       objWMIInstance.ForceRefresh()  ...:  938:       WScript.Echo "Zone '" & strZoneName & "' refreshed."  ...:  941:    End If  942:    If boolZONEPause Then  943:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Zone." & _  944:                                  "ContainerName='" & strZoneName & _  945:                                  "',DnsServerName='" & strDNSServerName & _  946:                                  "',Name='" & strZoneName & "'")  ...:  949:       objWMIInstance.PauseZone()  ...:  952:       WScript.Echo "Zone '" & strZoneName & "' paused."  ...:  955:    End If  956:    If boolZONEReLoad Then  957:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Zone." & _  958:                                  "ContainerName='" & strZoneName & _  959:                                  "',DnsServerName='" & strDNSServerName & _  960:                                  "',Name='" & strZoneName & "'")  ...:  963:       objWMIInstance.ReloadZone()  ...:  966:       WScript.Echo "Zone '" & strZoneName & "' reloaded."  ...:  969:    End If  970:    If boolZONEReset2 Then  971:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Zone." & _  972:                                  "ContainerName='" & strZoneName & _  973:                                  "',DnsServerName='" & strDNSServerName & _  974:                                  "',Name='" & strZoneName & "'")  ...:  977:       objWMIInstance.ResetSecondaries arraySecondaryServers, _  978:                                       intSecureSecondaries, _  979:                                       arrayNotifyServers, _  980:                                       intZoneNotify  ...:  983:       WScript.Echo "Secondaries of zone '" & strZoneName & "' reset."  ...:  986:    End If  987:    If boolZONEResume Then  988:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Zone." & _  989:                                  "ContainerName='" & strZoneName & _  990:                                 "',DnsServerName='" & strDNSServerName & _  991:                                 "',Name='" & strZoneName & "'")  ...:  994:       objWMIInstance.ResumeZone()  ...:  997:       WScript.Echo "Zone '" & strZoneName & "' resumed."  ...: 1000:    End If 1001:    If boolZONEUpdate Then 1002:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Zone." & _ 1003:                                  "ContainerName='" & strZoneName & _ 1004:                                  "',DnsServerName='" & strDNSServerName & _ 1005:                                  "',Name='" & strZoneName & "'") ....: 1008:       objWMIInstance.UpdateFromDS() ....: 1011:       WScript.Echo "Zone '" & strZoneName & "' updated from DS." ....: 1014:    End If 1015:    If boolZONEWrite Then 1016:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Zone." & _ 1017:                                  "ContainerName='" & strZoneName & _ 1018:                                  "',DnsServerName='" & strDNSServerName & _ 1019:                                  "',Name='" & strZoneName & "'") ....: 1022:       objWMIInstance.WriteBackZone() ....: 1025:       WScript.Echo "Zone '" & strZoneName & "' WriteBack completed." ....: 1028:    End If 1029:    If boolCACHEClear Then 1030:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_Cache." & _ 1031:                                  "ContainerName='..Cache" & _ 1032:                                  "',DnsServerName='" & strDNSServerName & _ 1033:                                  "',Name='..Cache'") ....: 1036:       objWMIInstance.ClearCache() ....: 1039:       WScript.Echo "DNS cache cleared." ....: 1042:    End If 1043:    If boolROOTHWrite Then 1044:       Set objWMIInstance = objWMIServices.Get ("MicrosoftDNS_RootHints." & _ 1045:                                  "ContainerName='..RootHints" & _ 1046:                                  "',DnsServerName='" & strDNSServerName & _ 1047:                                  "',Name='..RootHints'") ....: 1050:       objWMIInstance.WriteBackRootHintDatafile() ....: 1053:       WScript.Echo "Roothints WriteBack completed." ....: 1056:    End If 1057: ....: ....: ....: 

    end example

  • A portion to manage the DNS records, shown in Sample 3.69

    Sample 3.69: Managing the DNS records (Part III)

    start example

     ....: ....: ....: 1057: 1058:    ' -------------------------------------------------------------------------------------------------------------- 1059:    If boolRECView Then 1060:       Set objWMIInstances = objWMIServices.ExecQuery ("Select * From " & _ 1061:                                            strWMIClassRecordType & _ 1062:                                            " Where ContainerName='" & _ 1063:                                            strDomainName & " ' ") ....: 1066:       WScript.Echo "All '" & DecodeRecordClassString (strWMIClassRecordType) & _ 1067:                    "' records of domain '" & _ 1068:                    strDomainName & _ 1069:                    " ' . " & vbCRLF 1070: 1071:       For Each objWMIInstance In objWMIInstances 1072:          Set objWMIPropertySet = objWMIInstance.Properties_ 1073:          For Each objWMIProperty In objWMIPropertySet 1074:              Select Case objWMIProperty.Name 1075:                     Case "ContainerName" 1076:                     Case "TextRepresentation" 1077:                     Case "InstallDate" 1078:                     Case "DomainName" 1079:                     Case "RecordData" 1080:                     Case "RecordClass" 1081:                          DisplayFormattedProperty objWMIInstance, _ 1082:                                 "  " & objWMIProperty.Name, _ 1083:                                 DecodeRecordClass (objWMIProperty.Value), _ 1084:                                 Null 1085:                     Case Else 1086:                          DisplayFormattedProperty objWMIInstance, _ 1087:                                 "  " & objWMIProperty.Name, _ 1088:                                 objWMIProperty.Name, _ 1089:                                 Null 1090:              End Select 1091:          Next 1092:          WScript.Echo ....: 1095:       Next ....: 1098:    End If 1099:    If boolRECCreate Then 1100:       Set objWMIClass = objWMIServices.Get (strWMIClassRecordType) ....: 1103:       objWMIClass.CreateInstanceFromPropertyData strDNSServerName, _ 1104:                                                  strDomainName, _ 1105:                                                  strHostOwner & _ 1106:                                                  "." & strDomainName, _ 1107:                                                  intRecordClass, _ 1108:                                                  intTTL, _ 1109:                                                  strHostAddress ....: 1112:       WScript.Echo "'" & strRecordType & "' record for '" & _ 1113:                    strHostOwner & "." & strDomainName & "' created." ....: 1116:    End If 1117:    If boolRECDelete Then 1118:       Set objWMIInstance = objWMIServices.Get (strWMIClassRecordType & _ 1119:                               ".ContainerName='" & strDomainName & _ 1120:                               "',DnsServerName='" & strDNSServerName & _ 1121:                               "',DomainName='" & strDomainName & _ 1122:                               "',OwnerName='" & strHostOwner & "." & strDomainName & _ 1123:                               "',Record,RecordData='" & strHostAddress & "'") ....: 1127:       objWMIInstance.Delete_ ....: 1130:       WScript.Echo "'" & strRecordType & "' record for '" & _ 1131:                    strHostOwner & "." & strDomainName & "' deleted." ....: 1134:    End If 1135: 1136:    ]]> 1137:    </script> 1138:  </job> 1139:</package> 

    end example

Once the WMI connection is established in the Root\MicrosoftDNS namespace (lines 569 through 573), the script retrieves the name of the DNS server available in the system (lines 576 through 582). Normally, we only have one DNS server per system, which means that we may expect the MicrosoftDNS_Server class to be defined as a singleton class. However, the class definition is not made that way, since it uses a key property called name, which contains the FQDN of the DNS server (line 580). The FQDN of the server is retrieved at the beginning of the script, simply because its name will be used to manage the server, the zones, and the records.

The rest of the script makes use of some of the MicrosoftDNS_Server methods and properties (lines 587 through 757).

To manage, view, and update the DNS server information, the script always retrieves the DNS server instance first. Sample 3.66 contains several subportions, which are dedicated to a particular management task that can be performed with the DNS server. The tasks are the following:

  • Viewing the DNS information (lines 587 through 619): These lines retrieve the DNS server instance and show all properties by using the DisplayFormattedProperty() function previously developed (lines 593 through 599). Because it is interesting to see the domain zones hosted on the DNS server, the script uses the associations in place to retrieve the domain list available from this server (lines 606 through 615). The following command-line would give an output such as:

      1:   C:\>WMIDNS.Wsf Server View  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:   - net-dpen6400a.LissWare.Net --------------------------------------------  6:     AddressAnswerLimit: .................... 0  7:     AllowUpdate: ........................... 2  8:     AutoCacheUpdate: ....................... FALSE  9:     AutoConfigFileZones: ................... 1 10:     BindSecondaries: ....................... TRUE 11:     BootMethod: ............................ 2 12:     DefaultAgingState: ..................... FALSE 13:     DefaultNoRefreshInterval: .............. 168 14:     DefaultRefreshInterval: ................ 168 15:     DisableAutoReverseZones: ............... FALSE 16:     DisjointNets: .......................... FALSE 17:     DsAvailable: ........................... TRUE 18:     DsPollingInterval: ..................... 300 19:     DsTombstoneInterval: ................... 604800 20:     EDnsCacheTimeout: ...................... 86400 21:     EnableDirectoryPartitions: ............. TRUE 22:     EnableDnsSec: .......................... 1 23:     EnableEDnsProbes: ...................... TRUE 24:     EventLogLevel: ......................... 2 25:     ForwardDelegations: .................... 0 26:     Forwarders: ............................ 10.10.10.1 27:     ForwardingTimeout: ..................... 5 28:     InstallDate: ........................... 01-01-2000 29:     IsSlave: ............................... FALSE 30:     ListenAddresses: ....................... 10.10.10.3 31:     LocalNetPriority: ...................... TRUE 32:     LogFileMaxSize: ........................ 500000000 33:     LogLevel: .............................. 0 34:     LooseWildcarding: ...................... FALSE 35:     MaxCacheTTL: ........................... 86400 36:     MaxNegativeCacheTTL: ................... 900 37:     *Name: ................................. net-dpen6400a.LissWare.Net 38:     NameCheckFlag: ......................... 2 39:     NoRecursion: ........................... FALSE 40:     RecursionRetry: ........................ 3 41:     RecursionTimeout: ...................... 15 42:     RoundRobin: ............................ TRUE 43:     RpcProtocol: ........................... -1 44:     ScavengingInterval: .................... 0 45:     SecureResponses: ....................... TRUE 46:     SendPort: .............................. 0 47:     ServerAddresses: ....................... 10.10.10.3 48:     Started: ............................... TRUE 49:     StartMode: ............................. Automatic 50:     Status: ................................ OK 51:     StrictFileParsing: ..................... FALSE 52:     UpdateOptions: ......................... 783 53:     Version: ............................... 235274501 54:     WriteAuthorityNS: ...................... FALSE 55:     XfrConnectTimeout: ..................... 30 56: 57:   - Hosted zones ------------------------------------------------------------ 58:     _msdcs.LissWare.Net 59:     0.in-addr.arpa 60:     10.in-addr.arpa 61:     127.in-addr.arpa 62:     255.in-addr.arpa 63:     LissWare.Net 64:     LissWare.Net 

    We see the MicrosoftDNS_Server class properties from line 6 through 55 and the MicrosoftDNS_Zone associated instances from line 58 through 64.

  • Starting the DNS server service (lines 620 through 631): The MicrosoftDNS_Server class is derived from the CIM_Service class. We have seen that this standard class exposes methods to start and stop a service. With the class inheritance mechanism of the CIM repository, the MicrosoftDNS_Server class also exposes these methods. This portion of the code makes use of the StartService method to start the DNS service (line 625).

  • Stopping the DNS server service (lines 632 through 643): This portion of the code makes use of the StopService method coming from the CIM_Service class to stop the DNS service (line 637).

  • Scavenging the DNS server (lines 644 through 652): Scavenging is the mechanism to perform cleanup and removal of stale DNS resource records, which can accumulate in zone data over time. By invoking the StartScavenging method of the MicrosoftDNS_Server class, it is possible to launch this cleanup process (line 648).

  • Setting the DNS boot method (lines 653 through 667): A DNS server can be booted from a data file, the Windows Registry (default), or Active Directory. The BootMethod property defines the boot method to use (line 658). The boot method values are shown in Table 3.64.

    Table 3.64: Some DNS Server Property Values

    Server boot

    Value

    File

    1

    Registry

    2

    Active Directory & Registry

    3

    Server Events Log Level

    Value

    None

    0

    Errors only

    1

    Errors & Warnings

    2

    All events

    7

    Debug Log Level

    Value

    Query

    1

    Notify

    16

    Update

    32

    Nonquery transactions

    254

    Questions

    256

    Answers

    512

    Send

    4096

    Receive

    8192

    UDP

    16384

    TCP

    32768

    All packets

    65535

    NT Directory Service write transaction

    65536

    NT Directory Service update transaction

    131072

    Full Packets

    16777216

    Write Through

    2147483648

  • Setting the DNS log level (lines 668 through 682): The event logging level can be changed by setting the EventLogLevel property (line 673). The logging level values are also shown in Table 3.64. Do not confuse the event logging level with the debug logging level, for which values are also shown in Table 3.64.

  • Setting the DNS forwarders (lines 683 through 697): Because several forwarders can be defined for one single DNS server, the Forwarders property accepts an array of IP addresses that correspond to the forwarder list (line 688).

  • Setting the DNS server as a slave (lines 698 through 712): If the server must act as a slave, the IsSlave property of the MicrosoftDNS_Server class must be set to True (line 703).

  • Setting the DNS server recursion (lines 713 through 727): To disable the recursion for the naming resolution, the NoRecursion property of the MicrosoftDNS_Server class must be set to True (line 718). This property corresponds to one of the advanced server options. Note that it is impossible to set forwarders when the recursion is disabled.

  • Setting the DNS server round-robin (lines 728 through 742): If the DNS server must use the round-robin algorithm, which implements a load-balancing mechanism to share and distribute network resource loads, the RoundRobin property of the MicrosoftDNS_Server class must be set to True (line 733). This property corresponds to one of the advanced server options.

  • Setting the DNS server listening IP addresses (lines 743 through 757): To define the IP address interfaces on which the DNS server must listen for DNS requests, the ListenAddresses property accepts an array of IP addresses that correspond to the interface IP address list (line 748).

The next portion of the script manages the DNS zones. This portion is divided into two subportions: the first one displays all details related to one specific zone (lines 762 through 802); the second one displays an information summary about all zones available in a DNS server (lines 804 through 831).

Let's start with the second portion of the code, since it shows a zone information summary (lines 804 through 831). This part of the code is only executed when no specific zone name is given on the command line (line 761). For example, the following command line would give:

 C:\>WMIDNS.Wsf Zone View Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.                Zone          Name        Type Updates       Transfer      Notify list ... -----------------------------------------------------------------------------------------... _msdcs.LissWare.Net AD Integrated Only secure updates To any servers Only NS servers       0.in-addr.arpa       Primary         Not allowed To any servers Only NS servers ...     10.in-addr.arpa       Primary         Not allowed           None Only listed servers ...    127.in-addr.arpa       Primary         Not allowed To any servers Only NS servers ...    255.in-addr.arpa       Primary         Not allowed To any servers Only NS servers ...        LissWare.Net       Primary         Not allowed           None Only listed servers ...        LissWare.Net AD Integrated Only secure updates To any servers Only NS servers ... 

In opposition to the technique used to retrieve the existing zone list at the DNS server level (see Sample 3.66, lines 606 through 615), the script logic requests the list of all instances made from the MicrosoftDNS_Zone class (line 804). Of course, both methods are valid! This simply shows another scripting technique to retrieve the same information.

If the zone name is given on the command line, the script will retrieve all properties of the corresponding MicrosoftDNS_Zone instance. The output would be as follows:

  1:   C:\>WMIDNS.Wsf Zone View Name=LissWare.Net  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:   - LissWare.Net ------------------------------------------------------------  6:     Aging: ................................. TRUE  7:     AllowUpdate: ........................... Only secure updates  8:     AutoCreated: ........................... FALSE  9:     AvailForScavengeTime: .................. 3515052 10:     *ContainerName: ........................ LissWare.Net 11:     *DnsServerName: ........................ net-dpen6400a.LissWare.Net 12:     DsIntegrated: .......................... TRUE 13:     ForwarderSlave: ........................ FALSE 14:     ForwarderTimeout: ...................... 0 15:     InstallDate: ........................... 01-01-2000 16:     LastSuccessfulSoaCheck: ................ 0 17:     LastSuccessfulXfr: ..................... 0 18:     *Name: ................................. LissWare.Net 19:     NoRefreshInterval: ..................... 168 20:     Notify: ................................ Only NS servers 21:     Paused: ................................ FALSE 22:     RefreshInterval: ....................... 168 23:     Reverse: ............................... FALSE 24:     SecureSecondaries: ..................... To any servers 25:     Shutdown: .............................. FALSE 26:     UseWins: ............................... FALSE 27:     ZoneType: .............................. AD Integrated 

More than simply retrieving information available from the existing zones, the script is also capable of performing the usual zone management tasks, such as creating a zone, updating the zone properties, and deleting a zone. These tasks are implemented in Sample 3.68.

Here again, this portion can be divided into several subportions. Each portion corresponds to a management task that can be performed with a specific DNS zone. The tasks are as follows:

  • Creating a new zone (lines 836 through 872): To create a zone we use the CreateZone method exposed by the MicrosoftDNS_Zone class. This method is invoked from the class instance (line 837), since the CreateZone method is defined as a static method (you can check the static qualifier present in the method qualifiers). It is interesting to note that based on the zone type to be created, not all method parameters are required. When an Active Directory integrated zone is created, only the zone name (line 842), the value defining the zone type (line 843), the Boolean value setting the zone as an Active Directory Integrated zone (True), and the zone administrator's email address must be given. When a standard primary zone is created, we have the same set of parameters, but the Active Directory Integrated Boolean value is set to False (line 848) and the zone data file name is added (line 849) in the parameter list. For a secondary zone, again, we have the same set of parameters as for a primary zone creation, but the zone type value is different (line 854) and the primary IP address from which to transfer the zone is added (line 857). Basically, for a stub zone, the parameters are the same as for a secondary zone creation. Only the zone type is different (line 861). The values for the zone type are shown in Table 3.65.

    Table 3.65: Some Zone Property Values

    Zone type

    Value

    Primary or AD Integrated

    0

    Secondary

    1

    Stub

    2

    Zone transfer

    Value

    To any servers

    0

    Only NS servers

    1

    Only listed servers

    2

    No zone transfer

    3

    Zone notify

    Value

    No notification

    0

    Only NS servers

    1

    Only listed servers

    2

    Zone update

    Value

    Not allowed

    0

    Allow updates

    1

    Allow only secure updates

    2

  • Updating the zone type and its related information (lines 873 through 913): To update an existing zone, the script uses the ChangeZoneType method exposed by the MicrosoftDNS_Zone class. Basically, the method follows the same rules as the CreateZone method in the sense that not all method parameters are required, based on the zone type update to perform (lines 880 through 901). However, the method must be invoked from an instance representing the zone to be updated (lines 874 through 877). For example, this method can be used to convert an Active Directory integrated zone into a standard primary zone. It is interesting to note that the ChangeZoneType method does not modify the zone update mode for the DNS dynamic updates. This property is stored in a specific property called AllowUpdate, which is updated after the method invocation in the script code (lines 904 through 907).

  • Deleting a zone (lines 914 through 927): To delete a zone from a DNS server, there is no specific method to use. The scripting technique simply retrieves the zone instance (lines 915 through 918) and invokes the Delete_ method of the SWBemObject representing the zone instance (line 921).

  • Forcing the refresh of a zone (lines 928 through 941): To refresh a DNS zone, the instance representing the zone must be retrieved (lines 929 through 932); next, the ForceRefresh method of the MicrosoftDNS_Zone instance must be invoked (line 935).

  • Pausing a zone (lines 942 through 955): In the same way as with the zone refresh, to pause a DNS zone, the PauseZone method must be invoked (line 949) from an instance representing the zone to be paused.

  • Reloading a zone (lines 956 through 969): To reload a zone, the technique is exactly the same. The script retrieves an instance of the zone (lines 957 through 960) and invokes the ReloadZone method (line 963).

  • Reconfiguring the secondary IP addresses (lines 970 through 986): To update the configuration related to the secondary IP addresses, a specific method must be used. This method is called ResetSecondaries and allows the modification of several secondary server parameters. The first parameter accepted by the method contains the list of IP addresses representing the secondary servers (line 977). Next, the second method parameter defines how the zone transfer must be performed (line 978). The third method parameter contains a list of IP addresses that represents the servers to be notified for the zone updates (line 979). The final method parameter contains a value defining how the notification must be made (line 980). The various values used by this method are summarized in Table 3.65.

  • Resuming a zone (lines 987 through 1000): Resuming a zone is the same as pausing a zone; the scripting technique is exactly the same.

  • Forcing a zone update (lines 1001 through 1014): In the same way, from a scripting technique point of view, forcing a zone update is the same as reloading a zone.

  • Saving the zone back to the persistent storage (lines 1015 through 1028): By invoking the WriteBackZone method, it is possible to force a save of the DNS zone information in a persistent storage. The persistent storage can be a zone file or Active Directory, based on the zone type.

  • Clearing the cache (lines 1029 through 1042): The DNS cache is represented with the MicrosoftDNS_Cache class. The container name for the DNS cache is "..cache" (line 1031). By invoking the ClearCache method of the MicrosoftDNS_Cache instance, it is possible to clear the DNS cache content.

  • Saving the Root Hints to the used storage (lines 1043 through 1056): The Root Hints are represented with the MicrosoftDNS_ RootHints class. The container name for the DNS Root Hints zone is called "..RootHints" (line 1045). By invoking the WriteBackRootHintDatafile method of the MicrosoftDNS_Zone class, it is possible to save the Root Hints to the Root Hints data file.

By using the specific classes representing DNS records, it is possible to manage the records contained in the DNS zones. This is the purpose of Sample 3.69. The first operation is to retrieve the records contained in a zone. This operation is executed from line 1059 through 1098.

To retrieve the records available in a zone, the script performs a WQL query with some criteria to ensure that only the records of the given zone are retrieved (lines 1060 through 1063). We see in the query that the WMI record class name is stored in a variable (line 1061). If the Rtype parameter given on the command-line is an asterisk (*), then the class name used is the MicrosoftDNS_ResourceRecord class. Because the MicrosoftDNS_ResourceRecord class is a superclass for all record type classes, the use of this class in the WQL query will retrieve all records available in the zone. If the Rtype parameter given on the command-line corresponds to a specific record type (i.e., A record or CNAME record), then only this record type will be viewed, and the class used in the WQL query will be the one corresponding to the record type (see Table 3.63 to get a list of the record type WMI classes). This class selection, based on the record type, is made during the command-line parameters parsing. The following command line will list all A records available in the LissWare.Net domain:

  1:   C:\>WMIDNS.Wsf Record View RType=A DomainName=LissWare.Net  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:   All 'A' records of domain 'LissWare.Net'.  6:  7:     *DnsServerName: ........................ net-dpen6400a.LissWare.Net  8:     IPAddress: ............................. 10.10.10.3  9:     *OwnerName: ............................ LissWare.Net 10:     RecordClass: ........................... IN 11:     TTL: ................................... 600 12: 13:     *DnsServerName: ........................ net-dpen6400a.LissWare. Net 14:     IPAddress: ............................. 10.10.10.253 15:     *OwnerName: ............................ Cisco-Brussels.LissWare.Net 16:     RecordClass: ........................... IN 17:     TTL: ................................... 3600 18: 19:     *DnsServerName: ........................ net-dpen6400a.LissWare.Net 20:     IPAddress: ............................. 10.10.10.3 21:     *OwnerName: ............................ DomainDnsZones.LissWare.Net 22:     RecordClass: ........................... IN 23:     TTL: ................................... 600 24: 25:     *DnsServerName: ........................ net-dpen6400a.LissWare.Net 26:     IPAddress: ............................. 10.10.10.3 27:     *OwnerName: ............................ ForestDnsZones.LissWare.Net 28:     RecordClass: ........................... IN 29:     TTL: ................................... 600 30: 31:     *DnsServerName: ........................ net-dpen6400a.LissWare.Net 32:     IPAddress: ............................. 192.10.10.3 33:     *OwnerName: ............................ ForestDnsZones.LissWare.Net 34:     RecordClass: ........................... IN 35:     TTL: ................................... 600 36: 37:     *DnsServerName: ........................ net-dpen6400a.LissWare.Net 38:     IPAddress: ............................. 10.10.10.3 39:     *OwnerName: ............................ net-dpen6400a.LissWare.Net 40:     RecordClass: ........................... IN 41:     TTL: ................................... 3600 42: 43:     *DnsServerName: ........................ net-dpen6400a.LissWare.Net 44:     IPAddress: ............................. 192.10.10.3 45:     *OwnerName: ............................ net-dpep6400.Emea.LissWare.Net 46:     RecordClass: ........................... IN 47:     TTL: ................................... 3600 48: 49:     *DnsServerName: ........................ net-dpen6400a.LissWare.Net 50:     IPAddress: ............................. 10.10.10.100 51:     *OwnerName: ............................ XP-PR001.LissWare.Net 52:     RecordClass: ........................... IN 53:     TTL: ................................... 1200 

To create a new DNS record, the CreateInstanceFromPropertyData method is used in the script code (lines 1099 through 1116). This method is specific to the DNS record type and is not available at the level of the MicrosoftDNS_ResourceRecord class. Note that it is possible to use a text representation of the record to create a new record in the DNS zone. In such a case, the CreateFromTextRepresentation method of the MicrosoftDNS_ResourceRecord class can be used. Using one method or the other will always create a DNS record. However, based on the situation, one method will be easier than the other. By using the generic CreateFromTextRepresentation method of the MicrosoftDNS_ResourceRecord class, it is possible to create any record type with one single parameter, which is the text representation of the record type. This makes the scripting technique easier, since only one method with one single parameter must be used. However, the correct text representation must be passed to the method. As an example, we have the text representation of an A record and a CNAME record:

 Net-dpen6400a.LissWare.Net IN A 10.10.10.3 www.LissWare.Net IN CNAME Net-dpen6400a.LissWare.Net. 

The second method, called CreatInstanceFromPropertyData, requires specific parameters determined by the record type to be created. In such a case, the scripting technique becomes specific to the record type but does not require the DNS record string representation. Currently, the script uses the CreatInstanceFromPropertyData method defined at the level of the MicrosoftDNS_Atype class. Because the MicrosoftDNS_CNAMEType class exposes the same method name with the same number of parameters, it is possible to create transparently with the CreatInstanceFromPropertyData method A and CNAME records, provided that the correct parameters are passed to the method. Although the number of parameters is the same, the meaning of all parameters between an A record and a CNAME record is not exactly the same. The two following command-line samples show the parameter difference:

 C:\>WMIDNS.Wsf Record Create RType=A DomainName=LissWare.Net Host=Net-dpen6400a Class=IN                              TTL=3600 HostAddress=10.10.10.7 C:\>WMIDNS.Wsf Record Create RType=CNAME DomainName=LissWare.Net Host=www Class=IN                              TTL=7200 HostAddress=Net-dpen6400a.LissWare.Net. 

We see that most parameters are the same. However, we notice that the HostAddress is an IP address when creating an A record and that HostAddress is an FQDN when creating a CNAME record. The record class remains the same in both cases. The values used to define the record class during the CreateInstanceFromPropertyData method invocation are listed in Table 3.66.

Table 3.66: The DNS Record Class Values

Record class

Value

IN (INTERNET)

1

CS (CSNET)

2

CH (CHAOS)

3

HS (HESIOD)

4

The scripting technique to delete a record is very similar to the technique used to delete a zone. The first step is to retrieve an instance of the record (lines 1118 through 1124) and then to invoke the Delete_ method of the SWBemObject representing the record instance (line 1127). To delete a DNS record, the following command-line parameter can be used:

 C:>\WMIDNS.Wsf Record Delete RType=A DomainName=LissWare.Net Host=Net-dpen6400a Class=IN                              TTL=3600 HostAddress=10.10.10.7 

3.7.5 SNMP providers

The WMI SNMP providers are designed to integrate the Simple Network Management Protocol (SNMP) management information in WMI, which means that it is possible to seamlessly manage SNMP devices from WMI. By default, none of the SNMP providers is installed on any Windows platform! So, to install these providers, you should perform the following tasks:

  • For Windows XP and Windows Server 2003: From the control panel, select Add/Remove Programs. Next, select Add/Remove Windows Components, and then in the Windows Components Wizard, select Management and Monitoring Tools (see Figure 3.39).

    click to expand
    Figure 3.39: Adding the SNMP providers under Windows Server 2003.

    Finally, select WMI SNMP providers, then click OK. Follow the steps in the wizard to complete the installation.

  • For Windows 2000: Run the SNMP provider Setup program, Wbemsnmp.exe, from the System32\wbem directory or the \i386 directory of the Windows 2000 installation CD.

  • For Windows NT 4.0: Install the SNMP provider when installing the WMI core component or from the Internet at http://www.microsoft.com/downloads/details.aspx?FamilyID=f8130806-2589-46b3-b472-26b816776f31&DisplayLang=en.

Note that under Windows 95, 98, and Millennium, the WMI SNMP provider cannot be installed or run on this operating system.

The SNMP providers are made up of one instance provider, one class provider, and two event providers. (See Table 3.67.)

Table 3.67: The SNMP Providers Capabilities

Provider Name

Provider Namespace

Class Provider

Instance Provider

Method Provider

Property Provider

Event Provider

Event Consumer Provider

Support Get

Support Put

Support Enumeration

Support Delete

Windows Server 2003

Windows XP

Windows 2000 Server

Windows 2000 Professional

Windows NT 4.0

SNMP Providers

MS_SNMP_CLASS_PROVIDER

Root/snmp/localhost

X

X

X

X

X

X

X

X

MS_SNMP_ENCAPSULATED_EVENT_PROVIDER

Root/snmp/localhost

X

X

X

X

X

X

MS_SNMP_INSTANCE_PROVIDER

Root/snmp/localhost

X

X

X

X

X

X

X

X

X

X

MS_SNMP_REFERENT_EVENT_PROVIDER

Root/snmp/localhost

X

X

X

X

X

X

Once the SNMP providers are installed, by default two new namespaces are created: the Root\SNMP\SMIR and the Root\SNMP\LocalHost. The Root\SNMP\SMIR namespace contains the SNMP schema database, which is called the SNMP Module Information Repository (SMIR). SNMP definitions, called the Structure of Management Information (SMI), are available from Management Information Base (MIB) files and represent the real-world manageable entities as defined by SNMP. MIB files use a standard notation (Abstract Syntax Notation 1 or ASN.1) and a number of macro definitions that serve as templates to describe real-world manageable entities. We will not go into the syntax details of MIB files, but it is important to realize that MIB files are the primary source of information used by WMI to represent these real-world SNMP manageable entities in the CIM repository. By default, the WMI installation only loads MIB definitions from the RFC 1213 and RFC 1215 MIB files that define standard MIB to manage IP networks. (See Table 3.68.)

Table 3.68: The SNMP Classes Available in the Root\SNMP\SMIR Namespaces

Name

Type

Comments

SNMP_RFC1213_MIB_atTable

Dynamic

The Address Translation tables contain the NetworkAddress to 'physical' address equivalences. Some interfaces do not use translation tables for determining address equivalences (e.g., DDN-X.25 has an algorithmic method); if all interfaces are of this type, then the Address Translation table is empty (i.e., has zero entries).

SNMP_RFC1213_MIB_egp

Dynamic

The Exterior Gateway Protocol (EGP) group represents information about: The number of EGP messages received without error, the number of EGP messages received that proved to be in error, the total number of locally generated EGP messages, and the number of locally generated EGP messages not sent due to resource limitations within an EGP entity.

SNMP_RFC1213_MIB_egpNeighTable

Dynamic

The Exterior Gateway Protocol (EGP) neighbor table contains information about this entity's EGP neighbors.

SNMP_RFC1213_MIB_icmp

Dynamic

The ICMP group represents information about ICMP messages (number of messages, errors, unreachable destinations, exceeded time, redirections, etc.).

SNMP_RFC1213_MIB_ifTable

Dynamic

A list of interface entries. The number of entries is given by the value of ifNumber.

SNMP_RFC1213_MIB_interfaces

Dynamic

Represent the number of network interfaces (regardless of their current state) present on this system (ifNumber).

SNMP_RFC1213_MIB_ip

Dynamic

The IP group represents information about IP Forwarding, IP TTL, IP traffic, IP errors. Datagrams, packets discarded, etc.

SNMP_RFC1213_MIB_ipAddrTable

Dynamic

The table of addressing information relevant to this entity's IP addresses.

SNMP_RFC1213_MIB_ipNetToMediaTable

Dynamic

The IP Address Translation table used for mapping from IP addresses to physical addresses.

SNMP_RFC1213_MIB_ipRouteTable

Dynamic

The entity's IP Routing table.

SNMP_RFC1213_MIB_snmp

Dynamic

The entity's SNMP information.

SNMP_RFC1213_MIB_system

Dynamic

The entity's system information (contact, location, etc.).

SNMP_RFC1213_MIB_tcp

Dynamic

The TCP group represents information about TCP stack (open connections, errors, packet transmit and receive, etc.).

SNMP_RFC1213_MIB_tcpConnTable

Dynamic

Table containing active TCP connections information.

SNMP_RFC1213_MIB_udp

Dynamic

The UDP group represent information about UDP stack (datagrams, errors, packet transmit and receive, etc.)

SNMP_RFC1213_MIB_udpTable

Dynamic

Table containing UDP listener information.

SnmpV1ExtendedNotification

Extrinsic (Enterprise non-specific)

SNMP version 1 Enterprise nonspecific events.

SnmpV1Notification

Extrinsic (Enterprise non-specific)

SNMP version 1 Enterprise nonspecific events.

SnmpV2ExtendedNotification

Extrinsic (Enterprise non-specific)

SNMP version 2 Enterprise nonspecific events.

SnmpV2Notification

Extrinsic (Enterprise non-specific)

SNMP version 2 Enterprise nonspecific events.

SnmpAuthenticationFailureExtendedNotification

Extrinsic (Generic)

Notification representing an authentication failure.

SnmpAuthenticationFailureNotification

Extrinsic (Generic)

Notification representing an authentication failure.

SnmpColdStartExtendedNotification

Extrinsic (Generic)

Notification representing an SNMP device cold start.

SnmpColdStartNotification

Extrinsic (Generic)

Notification representing an SNMP device cold start.

SnmpEGPNeighborLossExtendedNotification

Extrinsic (Generic)

Notification representing an Exterior Gateway Protocol (EGP) neighbor loss.

SnmpEGPNeighborLossNotification

Extrinsic (Generic)

Notification representing an Exterior Gateway Protocol (EGP) neighbor loss.

SnmpExtendedNotification

Extrinsic (Generic)

The SnmpExtendedNotification class is the base class for any class mapped from the NOTIFICATION-TYPE macro to a CIM class by the SNMP Provider.

SnmpLinkDownExtendedNotification

Extrinsic (Generic)

Notification representing an interface link down.

SnmpLinkDownNotification

Extrinsic (Generic)

Notification representing an interface link down.

SnmpLinkUpExtendedNotification

Extrinsic (Generic)

Notification representing an interface link up.

SnmpLinkUpNotification

Extrinsic (Generic)

Notification representing an interface link up.

SnmpNotification

Extrinsic (Generic)

The SnmpNotification class is the base class for any dass mapped from the NOTIFICATION-TYPE macro to an encapsulated CIM class by the SNMP Provider.

SnmpWarmStartExtendedNotification

Extrinsic (Generic)

Notification representing an SNMP device warm start.

SnmpWarmStartNotification

Extrinsic (Generic)

Notification representing an SNMP device warm start.

Both RFC 1213 and RFC 1215 MIB are loaded in the SNMP Module Information Repository (Root\SNMP\SMIR) namespace and are represented in the form of WMI classes, as shown in Figure 3.40.

click to expand
Figure 3.40: The SNMP Module Information Repository classes in Root\SNMP\SMIR.

Of course, since these classes represent SNMP information, we leave the world of WMI to go into the world of SNMP. Although some class names reflect very well the information they provide, you can refer to RFC 1213 and RFC 1215 to get more information (see http://www.faqs.org/rfcs/rfcl213.html and http://www.faqs.org/rfcs/rfc1215.html). We have dynamic classes, which are used to represent SNMP instances from RFC 1213 (left side of Figure 3.40), and extrinsic event classes, which represent SNMP event classes from RFC 1215, usually called SNMP traps or notifications (right side of Figure 3.40).

The SNMP dynamic class provider uses the SNMP Module Information Repository to create and retrieve class definitions. It is important to note that the SMIR namespace does not contain the SNMP provider registration instances (made from the __Win32Provider class). This namespace is just used as a repository containing the SNMP MIB definitions to be used by WMI. Of course, there are a lot of things to say about the WMI SNMP providers and their integration with WMI. However, in the context of this book, instead of doing long theoretical descriptions, we will show you how you can take advantage of this integration. And by practicing, you will understand how things work together.

3.7.5.1 Accessing SNMP data

To access SNMP information available from a Windows system, ensure that the SNMP service is properly configured and running, since it implements the SNMP agent contacted to provide information (see Figure 3.41).

click to expand
Figure 3.41: The SNMP service configuration.

Next, we can use the Root\SNMP\Localhost namespace created during the installation of the WMI SNMP providers. This namespace is an SNMP proxy namespace and contains registration instances of the WMI SNMP providers (made from the _Win32Provider class). By default, all WMI SNMP providers are available from this namespace (instance, class, and event providers).

Each SNMP proxy WMI namespace has a set of qualifiers that describe the transport characteristics for communicating with an SNMP agent. In the case of the local system, there is one qualifier, called AgentAddress, defining the host name of the system, which in this case is the localhost (see Figure 3.42).

click to expand
Figure 3.42: The Root\SNMP\localhost namespace qualifier.

The AgentAddress is the only mandatory qualifier; however, there are other qualifiers defining other SNMP communication parameters. Table 3.69 summarizes the available qualifiers.

Table 3.69: The Proxy Namespace Qualifiers to Define SNMP Transport Characteristics

AgentAddress

CIM_STRING

Mandatory

Transport address associated with the SNMP agent, such as an IP address or DNS name. AgentAddress should be set to a valid unicast host address or a domain host name that can be resolved through the operating system's domain-name resolution process. There is no default value.

AgentTransport

CIM_STRING

Optional

Transport protocol used to communicate with the SNMP agent. Currently the only valid values are Internet Protocol (IP) and Internet Packet Exchange (IPX). The default value is IP.

AgentReadComm unity Name

CIM_STRING

Optional

Variable-length octet string that is used by the SNMP agent to authenticate an SNMP Protocol Data Unit(PDU) during a read operation (SNMP GET/GET NEXT requests). The community name must be mapped to a Unicode string and is limited to alphanumeric characters. The default value is public.

AgentWriteCommunityName

CIM_STRING

Optional

Variable-length octet string that is used by the SNMP agent to authenticate an SNMP Protocol Data Unit(PDU) during a read operation (SNMP SET request). The community name must be mapped to a Unicode string and is limited to alphanumeric characters. The default value is public.

AgentRetryCount

CIM_SINT32

Optional

Number of times a single SNMP request can be retried when there is no response from the SNMP agent before the request is deemed to have failed. AgentRetryCount must be set to an integer between 0 and 2^32-l. The default value is 1.

AgentRetryTimeout

CIM_SINT32

Optional

Time in milliseconds before the SNMP Protocol Data Unit (PDU) is considered to have been dropped. This is the number of milliseconds to wait for a response to an SNMP request sent to the SNMP agent. AgentRetryTimeout must be set to an integer between 0 and 2^32-1. The default value is 500.

AgentVarBindsPerPdu

CIM_SINT32

Optional

Maximum number of variable bindings contained within a single SNMP PDU. Every SNMP request sent to the SNMP agent contains one or more SNMP variables. This parameter specifies the largest number of variables that can be included in a single request. AgentVarBindsPerPdu can be set to 0 to cause the implementation to determine the optimal variable bindings or to an integer between 1 and 2^32-l. Note that while increasing this value can improve performance, some agents and networks cannot deal with the resulting request. The default value is 10.

AgentFlowControlWindowSize

CIM_SINT32

Optional

Maximum number of concurrently outstanding SNMP requests that can be sent to this agent while a response has not yet been received. An SNMP request is considered outstanding until a PDU response has been received or it has timed out. A large window size generally improves performance, but some agents might not work well under a heavy load. AgentFlowControlWindowSize can be set to 0 to indicate an infinite window size or to an integer between 1 and 2^32-l. The default value is 10.

Agents NMPVersion

CIM_SINT32

Optional

Version of the SNMP protocol to be used when communicating with the SNMP agent. Currently, the only valid values are 1 (for SNMPvl) and 2C (for SNMPv2C). The default value is 1.

Correlated

CIM_BOOLEAN

Optional

Set to True, defines the set of classes that a given SNMP agent is known to support at the time the enumeration occurs. Set to False, enumeration returns all classes present within the SMIR namespace (noncorrelated), regard less of whether the agent device supports them or not.

As you can see, you can use the AgentReadCommunityName to define the SNMP community string (public by default) or the AgentTransport to define the protocol type (IP by default, but it can be IPX). Let's take an example where a computer is using the following IP address and mask settings:

 C:\>ipconfig Windows 2000 IP Configuration Ethernet adapter Local Area Connection:         Connection-specific DNS Suffix  . :         IP Address. . . . . . . . . . . . : 10.10.10.3         Subnet Mask . . . . . . . . . . . : 255.0.0.0         Default Gateway . . . . . . . . . : 10.10.10.254 

By using Sample 3.70, we can obtain from WMI and via SNMP the same type of information.

Sample 3.70: Obtaining localhost IP addresses from WMI via SNMP

start example

  1:<?xml version="1.0"?>  .:  8:<package>  9:  <job> 10: 11:    <?job error="True" debug="True" ?> 12: 13:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertiesFunction.vbs" /> 14:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertyFunction.vbs" /> 15: 16:    <object prog  reference="true"/> 17:    <object prog  /> 18: 19:    <script language="VBscript"> 20:    <![CDATA[ ..: 24:    Const cComputerName = "LocalHost" 25:    Const cWMINameSpace = "Root/SNMP/LocalHost" 26:    Const cWMIClass = "SNMP_RFC1213_MIB_ipAddrTable" ..: 33:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 34:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 35:    Set objWMIServices = objWMILocator.ConnectServer(cComputerName, cWMINameSpace, "", "") 36: 37:    Set objWMIInstances = objWMIServices.InstancesOf(cWMIClass) 38: 39:    For Each objWMIInstance In objWMIInstances 40:        DisplayFormattedProperties objWMIInstance, 0 41:        WScript.Echo 42:    Next ..: 47:    ]]> 48:    </script> 49:  </job> 50:</package> 

end example

Sample 3.70 contains nothing complicated from a scripting point of view. We developed this script throughout the first book, Understanding WMI Scripting, when discovering the WMI Scripting API (see Sample 4.6 in the appendix). This demonstrates how transparent SNMP access is from WMI. We just need to access the appropriate WMI namespace (line 25) and request the SNMP_RFC1213_MIB_ipAddrTable class, which represents the requested SNMP information (line 26). The output would be as follows:

  1:   C:\>GetSingleInstanceWithAPI.wsf  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:  6:   - SNMP_RFC1213_MIB_ipAddrTable ----------------------------------------------------  7:   *ipAdEntAddr: ............................ 10.10.10.3  8:   ipAdEntBcastAddr: ........................ 1  9:   ipAdEntIfIndex: .......................... 33554434 10:   ipAdEntNetMask: .......................... 255.0.0.0 11:   ipAdEntReasmMaxSize: ..................... 65535 12: 13: 14:   - SNMP_RFC1213_MIB_ipAddrTable ---------------------------------------------------- 15:   *ipAdEntAddr: ............................ 127.0.0.1 16:   ipAdEntBcastAddr: ........................ 1 17:   ipAdEntIfIndex: .......................... 1 18:   ipAdEntNetMask: .......................... 255.0.0.0 19:   ipAdEntReasmMaxSize: ..................... 65535 

Accessing standard SNMP information from the local system is pretty straightforward, but how do you access SNMP information from a system other than the local host? We have two solutions: We can modify Sample 3.70 and make use of an SWBemNamedValueSet object, or we can create a new proxy namespace for that particular device or host. For this exercise, we will access via SNMP, a Cisco router 2503 loaded with the Cisco Internetwork Operating System (IOS) Software version 11.2(3)P If you plan to use another SNMP-enabled device, please refer to the device specifications to determine if it supports RFC 1213 and RFC 1215. For the Cisco IOS, these RFCs are supported from version 10.2 or later.

First, the Cisco router must be SNMP enabled. If you are not familiar with Cisco devices, please contact your network administrator to get some help for the Cisco configuration. Figure 3.43 shows the basic commands that are required to SNMP enable a Cisco router 2500. The router can be easily configured via a TELNET session, assuming it is preconfigured for TELNET access and you have the required credentials.

click to expand
Figure 3.43: Enabling SNMP on your Cisco router.

As you can see in Figure 3.43, you can easily recognize the SNMP community string for the read-only operations (RO=public) and read/write operations (RW=private). Make sure that you use the correct community string for the SNMP agent; otherwise, you won't be able to access the Cisco router. Note that the read/write community string is optional in this example (actually, we will also send SNMP commands to the device in section 3.7.5.5, "Sending SNMP commands"). Again, request the help of your network administrator to correctly configure the SNMP information in your Cisco router, and, if you configure this in production, make sure that you respect the security policies of your company.

To access a remote SNMP device, we mentioned two options:

  • Using an SWBemNamedValueSet object

  • Creating a new WMI namespace

Let's start with the first one by using an SWBemNamedValueSet object. In this case, we do not create a dedicated namespace for the device as for the localhost. However, we reuse the existing namespace created for the localhost. This logic is shown in Sample 3.71.

Sample 3.71: Obtaining remote device IP addresses from WMI via SNMP

start example

  1:<?xml version="1.0"?>  .:  8:<package>  9:  <job> ..: 13:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertiesFunction.vbs" /> 14:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertyFunction.vbs" /> 15: 16:    <object prog  reference="true"/> 17:    <object prog  /> 18:    <object prog  /> 19: 20:    <script language="VBscript"> 21:    <![CDATA[ ..: 25:    Const cComputerName = "LocalHost" 26:    Const cWMINameSpace = "Root/SNMP/LocalHost" 27:    Const cWMIClass = "SNMP_RFC1213_MIB_ipAddrTable" ..: 34:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 35:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 36:    Set objWMIServices = objWMILocator.ConnectServer(cComputerName, cWMINameSpace, "", "") 37: 38:    objWMINamedValueSet.Add "Correlate", True 39:    objWMINamedValueSet.Add "AgentAddress", "Cisco-Brussels.LissWare.Net" 40:    objWMINamedValueSet.Add "AgentFlowControlWindowSize", 3 41:    objWMINamedValueSet.Add "AgentReadCommunityName", "public" 42:    objWMINamedValueSet.Add "AgentRetryCount", 1 43:    objWMINamedValueSet.Add "AgentRetryTimeout", 500 44:    objWMINamedValueSet.Add "AgentVarBindsPerPdu", 10 45:    objWMINamedValueSet.Add "AgentWriteCommunityName", "private" 46: 47:    Set objWMIInstances = objWMIServices.InstancesOf(cWMIClass, _ 48:                                                     , _ 49:                                                     objWMINamedValueSet) 50: 51:    For Each objWMIInstance In objWMIInstances 52:        DisplayFormattedProperties objWMIInstance, 0 53:        WScript.Echo 54:    Next ..: 59:    ]]> 60:    </script> 61:  </job> 62:</package> 

end example

The script code is almost the same as Sample 3.70; only the initialization of the SWBemNamedValueSet is new (lines 38 through 45). The SWBemNamedValueSet object instantiated at line 17 is initialized with the qualifiers listed in Table 3.69. Note that the script uses all supported qualifiers. This is, of course, not mandatory, but it shows the complete coding technique. Passing the SWBemNamedValueSet object when requesting the collection of instances (line 49) supersedes the qualifiers defined at the Root\SNMP\Localhost namespace level (see Figure 3.42).

We can see that the AgentAddress qualifier is set with the Fully Qualified Domain Name (FQDN) of the Cisco router (line 39), but it can also be the IP address. Depending on the Cisco router configuration, the output will look as follows:

  1:   C:\>GetSingleInstanceWithAPI2.wsf  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:  6:   - SNMP_RFC1213_MIB_ipAddrTable --------------------------------------------------------  7:   *ipAdEntAddr: ............................ 10.10.10.253  8:   ipAdEntBcastAddr: ........................ 1  9:   ipAdEntIfIndex: .......................... 1 10:   ipAdEntNetMask: .......................... 255.0.0.0 11:   ipAdEntReasmMaxSize: ..................... 18024 12: 13: 14:   - SNMP_RFC1213_MIB_ipAddrTable ---------------------------------------------------- 15:   *ipAdEntAddr: ............................ 192.10.10.253 16:   ipAdEntBcastAddr: ........................ 1 17:   ipAdEntIfIndex: .......................... 1 18:   ipAdEntNetMask: .......................... 255.255.255.0 19:   ipAdEntReasmMaxSize: ..................... 18024 20: 21: 22:   - SNMP_RFC1213_MIB_ipAddrTable ---------------------------------------------------- 23:   *ipAdEntAddr: ............................ 193.10.10.253 24:   ipAdEntBcastAddr: ........................ 1 25:   ipAdEntIfIndex: .......................... 1 26:   ipAdEntNetMask: .......................... 255.255.255.0 27:   ipAdEntReasmMaxSize: ..................... 18024 28: 29: 30:   - SNMP_RFC1213_MIB_ipAddrTable ---------------------------------------------------- 31:   *ipAdEntAddr: ............................ 194.10.10.253 32:   ipAdEntBcastAddr: ........................ 1 33:   ipAdEntIfIndex: .......................... 1 34:   ipAdEntNetMask: .......................... 255.255.255.0 35:   ipAdEntReasmMaxSize: ..................... 18024 36: 37: 38:   - SNMP_RFC1213_MIB_ipAddrTable ---------------------------------------------------- 39:   *ipAdEntAddr: ............................ 195.10.10.253 40:   ipAdEntBcastAddr: ........................ 1 41:   ipAdEntIfIndex: .......................... 2 42:   ipAdEntNetMask: .......................... 255.255.255.0 43:   ipAdEntReasmMaxSize: ..................... 18024 44: 45: 46:   - SNMP_RFC1213_MIB_ipAddrTable ---------------------------------------------------- 47:   *ipAdEntAddr: ............................ 200.10.10.1 48:   ipAdEntBcastAddr: ........................ 1 49:   ipAdEntIfIndex: .......................... 4 50:   ipAdEntNetMask: .......................... 255.255.255.0 51:   ipAdEntReasmMaxSize: ..................... 18024 

The second solution is to create a dedicated namespace to access the Cisco router. This namespace can be created with a MOF file. In the %SystemRoot%\System32\WBEM directory, there is a MOF file called SNMPREG.MOF. By using this MOF file as a template, it is very easy to obtain another MOF file to create the dedicated namespace to access the Cisco router. We will call this new namespace the Root\SNMP\CiscoBrussels namespace. The MOF file creating this namespace with the required qualifiers is shown in Sample 3.72. From line 10 through 32, the MOF file creates the Root\SNMP\CiscoBrussels namespace with the SNMP qualifiers defining the communication parameters (lines 13 through 26). Next, the subsequent lines are the exact copy of the information coming from the SNMPREG.MOF and define the registration information of the SNMP providers for the dedicated Cisco router namespace (lines 36 through 101).

Sample 3.72: A MOF file to create a dedicated namespace for an SNMP device

start example

  1:#pragma autorecover  2:  3:#pragma namespace("\\\\.\\Root")  4:  5:instance of __Namespace  6:{  7: Name = "SNMP" ;  8:} ;  9: 10:#pragma namespace("\\\\.\\Root\\snmp") 11: 12:[ 13:// IP address or DNS name. 14:AgentAddress ("Cisco-Brussels.LissWare.Net"), 15:// SNMP community name for SNMP GET/GETNEXT requests. 16:AgentReadCommunityName ("public"), 17:// SNMP community name for SNMP SET requests. 18:AgentWriteCommunityName ("private"), 19:// Number of SNMP PDU retries before transmission 20:AgentRetryCount (1), 21:// detects a 'No Response' from device. 22:AgentRetryTimeout (500), 23:// Maximum number of variable bindings contained within a single SNMP PDU. 24:AgentVarBindsPerPdu (10), 25:// Maximum number of outstanding SNMP PDUs that can be transmitted to an SNMP agent. 26:AgentFlowControlWindowSize (3) 27:] 28: 29:instance of __Namespace 30:{ 31:    Name = "CiscoBrussels" ; 32:} ; 33: 34:#pragma namespace("\\\\.\\Root\\snmp\\CiscoBrussels") 35: 36:instance of __Win32Provider as $PClass 37:{ 38:    Name = "MS_SNMP_CLASS_PROVIDER"; 39:    Clsid = "{70426720-F78F-11cf-9151-00AA00A4086C}"; 40:    HostingModel = "NetworkServiceHost"; 41:}; 42: 43:instance of __ClassProviderRegistration 44:{ 45:    Provider = $PClass; 46:    SupportsGet = TRUE; 47:    SupportsPut = FALSE; 48:    SupportsDelete = FALSE; 49:    SupportsEnumeration = TRUE; 50: 51:    QuerySupportLevels = NULL ; 52: 53:    ResultSetQueries = { "Select * From meta_class Where __this isa \"SnmpMacro\"", 54:                     "Select * From meta_class Where __this isa \"SnmpNotification\"", 55:                     "Select * From meta_class Where __this isa \"SnmpExtendedNotification\"" 56:                        } ; 57:} ; 58: 59:instance of __Win32Provider as $PInst 60:{ 61:    Name = "MS_SNMP_INSTANCE_PROVIDER"; 62:    Clsid = "{1F517A23-B29C-11cf-8C8D-00AA00A4086C}"; 63:    HostingModel = "NetworkServiceHost"; 64:}; 65: 66:instance of __InstanceProviderRegistration 67:{ 68:    Provider = $PInst; 69:    SupportsGet = TRUE; 70:    SupportsPut = TRUE; 71:    SupportsDelete = TRUE; 72:    SupportsEnumeration = TRUE; 73: 74:    QuerySupportLevels = { "WQL:UnarySelect" } ; 75:}; 76: 77:instance of __Win32Provider as $EventProv 78:{ 79:    Name = "MS_SNMP_REFERENT_EVENT_PROVIDER"; 80:    ClsId = "{9D5BED16-0765-11d1-AB2C-00C04FD9159E}"; 81:    HostingModel = "LocalSystemHost"; 82:}; 83: 84:instance of __EventProviderRegistration 85:{ 86:    Provider = $EventProv; 87:    EventQueryList = {"select * from SnmpExtendedNotification"} ; 88:}; 89: 90:instance of __Win32Provider as $EncapEventProv 91:{ 92:    Name = "MS_SNMP_ENCAPSULATED_EVENT_PROVIDER"; 93:    ClsId = "{19C813AC-FEE7-11D0-AB22-00C04FD9159E}"; 94:    HostingModel = "LocalSystemHost"; 95:}; 96: 97:instance of __EventProviderRegistration 98:{ 99:    Provider = $EncapEventProv; 100:    EventQueryList = {"select * from SnmpNotification"}; 101:}; 

end example

We compile this MOF file with MOFCOMP.EXE, as follows:

 C:\>MOFCOMP.Exe Cisco-Brussels-snmpreg.mof Microsoft (R) 32-bit MOF Compiler Version 1.50.1085.0007 Copyright (c) Microsoft Corp. 1997-1999. All rights reserved. Parsing MOF file: Cisco-Brussels-snmpreg.mof MOF file has been successfully parsed Storing data in the repository... Done! 

Next, we can simply edit Sample 3.70 ("Obtaining localhost IP addresses from WMI via SNMP") and change line 25:

   25:    Const cWMINameSpace = "Root/SNMP/LocalHost" 

to the following line:

   25:    Const cWMINameSpace = "Root/SNMP/CiscoBrussels" 

and we will obtain the exact same output as Sample 3.71 ("Obtaining remote device IP addresses from WMI via SNMP"), which was using an SWBemNamedValueSet object to pass the SNMP parameters.

3.7.5.2 Accessing SNMP private MIB information

Because we access a Cisco router, it is clear that we may find some specific SNMP information that is not defined in the standard RFC 1213. This SNMP information is called the private MIB information and is defined in other MIB files published by Cisco. You can get the Cisco MIB files from http://www.cisco.com/public/sw-center/netmgmt/cmtk/mibs.shtml. To access the private MIB information from WMI, it is necessary to load the MIB file information into the CIM repository. This can be done with the MIB compiler delivered with WMI, called SMI2SMIR.Exe, which basically converts the Structure of Management Information (SMI) format to the Structure of Management Information Repository (SMIR) format. Simply said, this utility converts a MIB file into a MOF file loadable in the CIM repository. To locate the information you are interested in, it must be clear that the challenge is not about WMI anymore but is a pure SNMP issue. Knowing the SNMP representation of the device you want to manage is key!

A Cisco router has a lot of private MIB information. So let's take a very easy example of private MIB information. For those of you who are not familiar with the Cisco routers, you should know that the device contains a flash memory, which contains the Cisco Internetwork Operating System (IOS). The IOS is nothing but a binary file stored in this flash memory. If you execute a TELNET session on the Cisco router and execute the show flash command, you will see the IOS binary file loaded in the flash (see Figure 3.44).

click to expand
Figure 3.44: The Cisco IOS loaded in the memory flash.

As we can see in Figure 3.44, we have an IOS binary file, called "c2500-c-l_112-3p.bin," of 4,271,008 bytes (4,171 KB) size. The flash memory card has a total size of 8,388,608 bytes (8 MB). To retrieve this information from WMI via SNMP, we must a use a private Cisco MIB file. This MIB file is called CISCO-FLASH-MIB.my and is available from the Cisco Web site for download. To successfully convert the MIB file into a MOF file, we also need the CISCO-SMI.my MIB file, since it contains definitions used in CISCO-FLASH-MIB.my. The conversion to a MOF file can be created, as shown in Sample 3.73.

Sample 3.73: Creating a private MIB in the CIM repository

start example

 C:\>smi2smir /m 0 /g CISCO-FLASH-MIB.my CISCO-SMI.my > CISCO-FLASH-MIB.MOF smi2smir : Version 1.50.1085.0000 : MIB definitions compiled from "CISCO-FLASH-MIB.my" smi2smir : Syntax Check successful on "CISCO-FLASH-MIB.my" smi2smir : Version 1.50.1085.0000 : MIB definitions compiled from "CISCO-SMI.my" smi2smir : Syntax Check successful on "CISCO-SMI.my" smi2smir : Semantic Check successful on "CISCO-FLASH-MIB.my" smi2smir: Generated MOF successfully 

end example

Note the presence of the redirection ">" character on the command line. SMI2SMIR.Exe outputs the generated MOF on the screen. So, if you want this in a file, you must redirect the output. Table 3.70 shows the complete list of command-line parameters for SMI2SMIR.Exe.

Table 3.70: The SMI2SMIR.Exe Command-Line Parameters

smi2smir[<DiagnosticArgs>] [<VersionArgs>] [<IncludeDirs>] <CommandArgs> <MIB file> [<Import Files>]

smi2smir[<DiagnosticArgs>] <RegistryArgs> [<Directory>]

smi2smir<ModulelnfoArgs> <MIB file>

smi2smir <HelpArgs>

DiagnosticArgs:

/m <diagnostic level>

Specifies the kind of diagnostics to display: 0 (silent), 1 (fatal), 2 (fatal and warning), or 3 (fatal, warning, and information messages).

/c <count>

Specifies the maximum number of fatal and warning messages to display.

Version Args:

/v1

Specifies strict conformance to the SNMPv1 SMI.

/v2c

Specifies strict conformance to the SNMPv2 SMI.

Command Args:

/d

Deletes the specified module from the SMIR.

/P

Deletes all modules in the SMIR.

/I

Lists all modules in the SMIR.

/Ic

Performs a local syntax check on the module.

/ec [< Command Modifier>]

Performs local and external checks on the module.

/a [<CommandModifier>]

Performs local and external checks and loads the module into the SMIR.

/sa [<CommandModifier>]

Same as /a, but works silently.

/g [<CommandModifier>]

Generates a SMIR MOF file that can be loaded later into CIMOM (using the MOF compiler). Used by the SNMP class provider to dynamically provide classes to one or more namespaces.

/gc [< Command Modifier]

Generates a static MOF file that can be loaded later into CIMOM as static classes for a particular namespace.

Command Modifiers:

/ch

Generates context information (date, time, host, user, etc.) in the MOF file header. Use with /g and /gc.

/t

Also generates SnmpNotification classes. Use with /a, /sa, and /g.

/ext

Also generates SnmpExtended Notification classes. Use with /a, /sa, and /g.

/t/o

Generates only SnmpNotification classes. Use with /a, /sa, and /g.

/ext /o

Generates only SnmpExtendedNotification classes. Use with /a, /sa, and /g.

/s

Does not map the text of the DESCRIPTION clause. Use with /a, /sa, /g, and /gc.

/auto

Rebuilds the MIB lookup table before completing <CommandArg> switch. Use with /ec, /a, /g, and /gc.

IncludeDirs:

/i <directory>

Specifies a directory to be searched for dependent MIB modules. Use with /ec, /a, /sa, /g, and /gc.

RegistryArgs:

/pa

Adds the specified directory to the registry (Default is current directory).

/pd

Deletes the specified directory from the registry (Default is current directory).

/pl

Lists the MIB lookup directories in the registry.

/r

Rebuilds the entire MIB lookup table.

ModuleInfoArgs:

/n

(Returns the ASN.1 name of the specified module.

/ni

Returns the ASN.1 names of all imports modules referenced by the input module.

HelpArgs:

/h

Displays this usage information.

/?

Displays this usage information.

For auto-detection of dependent MIBs, the following values of type REG MULTI_SZ must be set under the root key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WBEM\Providers\SNMP\Compiler:

  • "File Path" : An ordered list of directory names where MIBs are located.

  • "File Suffixes" : An ordered list of file extensions for MIB files.

Once the MOF file generated, it is ready to be loaded in the CIM repository, as follows:

 C:\>MOFCOMP.Exe CISCO-FLASH-MIB.MOF Microsoft (R) 32-bit MOF Compiler Version 1.50.1085.0007 Copyright (c) Microsoft Corp. 1997-1999. All rights reserved. Parsing MOF file: CISCO-FLASH-MIB.MOF MOF file has been successfully parsed Storing data in the repository... Done! 

Note that the MOF file will be loaded in the Root\SNMP\SMIR namespace. Once completed, the Root\SNMP\CiscoBrussels namespace should show WMI classes representing the Cisco Flash SNMP information, as shown in Figure 3.45. Ensure that the Cisco router is available on the network during this operation. If the Cisco router defined in the AgentAddress qualifier is not reachable, it is likely that the private MIB information stored in the MOF file will be improperly displayed.

click to expand
Figure 3.45: The Cisco Flash SNMP classes in the CIM repository.

If we reuse Sample 3.71 ("Obtaining remote device IP addresses from WMI via SNMP") and change line 27:

 27:    Const cWMIClass = "SNMP_RFC1213_MIB_ipAddrTable" 

to:

 27:    Const cWMIClass = "SNMP_CISCO_FLASH_MIB_ciscoFlashFileTable" 

we should obtain an output similar to this one:

  1:   C:\>GetSingleInstanceWithAPI2.wsf  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:  6:   - SNMP_CISCO_FLASH_MIB_ciscoFlashFileTable ----------------------------------------  7:   *ciscoFlashDeviceIndex: .................. 1  8:   ciscoFlashFileChecksum: .................. 3078424434  9:   *ciscoFlashFileIndex: .................... 1 10:   ciscoFlashFileName: ...................... c2500-c-l_112-3p.bin 11:   ciscoFlashFileSize: ...................... 4271008 12:   ciscoFlashFileStatus: .................... valid 13:   *ciscoFlashPartitionIndex: ............... 1 

We recognize the Cisco IOS binary file name (line 10) with its size (line 11), because we saw it in Figure 3.45. However, we do not see the flash memory size, because another WMI class, called SNMP_CISCO_FLASH_MIB_ciscoFlashPartitionTable, provides this information.

If the WMI classes representing the SNMP information are not shown, it is likely due to a feature part of the SNMP WMI providers called the correlation. Correlation might prevent you from seeing all classes that are actually supported by a device. In such a case, it could be wise to turn the correlation OFF. The side effect of turning correlation OFF is that many classes not supported by a device may appear in the SMIR. When correlation is turned ON, the SNMP provider causes an enumeration of device-supported classes, similar to the result of running an SNMP MIB walk operation. This could produce a performance cost in using correlation, because the device is queried to see what classes it supports. To set the correlation OFF, the Correlate parameter (or qualifier, if you use a dedicated namespace) set in the SWbemNamedValueSet object must be set to FALSE (OFF) or TRUE (ON). This value is set in Sample 3.71, line 38.

3.7.5.3 Organizing the SNMP data access

As we can see, based on the fact that the SNMP device is local or remote, uses a private MIB (i.e., Cisco device), and is WMI enabled (i.e., Windows computer), there are different options to access SNMP data. These various options can be quite confusing, since we have different ways of organizing the SNMP data in WMI and different protocols to access that information (i.e., RPC and SNMP). Let's try to summarize this with three figures showing the various options (see Figures 3.46 through 3.48).

click to expand
Figure 3.46: Accessing SNMP data via the localhost namespace and the SWBemNamedValueSet object.

The first option is the easiest one, since it consists of using the default SNMP CIM repository configuration and overriding some settings (i.e., AgentAddress) with an SWBemNamedValueSet object (see Figure 3.46) from the script. This technique gives the ability to access any SNMP device from any WMI computer in a Windows network, since no particular CIM repository customization is required. The developed script code can be run on any WMI computer. However, if some private MIB information must be accessed, it is necessary to load the related MIB information on a specific WMI system and connect the script to the WMI system where the private MIB information is loaded. An important point to note in this scenario is that SNMP is the only protocol used to access the desired information across the network.

The second technique consists of the creation of dedicated namespaces for each SNMP computer or device that must be accessed (see Figure 3.47). This technique requires a specific customization of the CIM repository and links the script to the system hosting the namespaces. Creating a dedicated namespace has the advantage of enabling the SNMP access to any tool running on top of WMI, since no specific logic is required to create an SWBemNamedValueSet object. Since all SNMP parameters are stored in the Qualifiers of the dedicated namespaces, any tool enumerating instances of the classes available in these namespaces will retrieve the SNMP information. As in the first case, the protocol used on the network is SNMP only. If some private MIB information must be accessed, the private MIB files must be loaded in the CIM repository.

click to expand
Figure 3.47: Accessing SNMP data via a dedicated namespace on the localhost.

The third technique is very similar to the second one (see Figure 3.48). However, in this case, the script code is run on a system where the dedicated namespaces are not available. Since WMI is COM/DCOM based, it is possible, by using the WMI scripting API (i.e., ConnectServer method of the SWBemServices object), to access a remote WMI host, which contains the dedicated namespace for the SNMP devices. Of course, as in the first technique, it is always possible to override the namespaces SNMP communication parameters in the remote hosts (Qualifiers) with an SWBemNamedValueSet object. The interesting feature in this last case is that you must authenticate to the remote WMI system first (on top of the COM/DCOM mechanisms, which are RPC based) and then access the SNMP devices, as done previously (via the SNMP protocol). If some private MIB information must be accessed, the private MIB files must be loaded in the CIM repository of the remote WMI system.

click to expand
Figure 3.48: Accessing SNMP data through a remote WMI computer via a dedicated namespace.

3.7.5.4 Receiving SNMP traps

With the WMI SNMP providers it is possible to receive SNMP traps or notifications in addition to simply retrieving SNMP information. If you remember, in the beginning of this section, we mentioned that the SNMP providers are also implemented as event providers. We must distinguish two event provider types:

  • SNMP Encapsulated Event provider (SEEP): The encapsulated provider means that the event instance has simple properties describing the information mapped directly from the SNMP trap. This corresponds to the SnmpNotification parent class with its subclasses.

  • SNMP Referent Event provider (SREP): The referent provider abstracts the information present within the SNMP trap so that properties that share the same class and instance are presented as embedded objects. This allows for the unique instance, with which the trap is associated, to be retrieved after the receipt of the event, using the SNMP __RELPATH. This corresponds to the SnmpExtendedNotification parent class with its subclasses.

In both cases, the same information is provided. Only the manner in which this information is presented and structured is different.

Figure 3.40 shows the event classes (left pane) supported by the SNMP event provider. The SNMP event providers support three types of traps or notifications:

  • Generic: These traps correspond to events such as link up and cold start. These traps are listed in Table 3.68. These classes are subclasses of the SnmpNotification and SnmpExtendedNotification classes.

  • Enterprise specific: These traps correspond to events that are represented by a WMI class that is not a subclass of the SnmpNotification and SnmpExtendedNotification classes. To support enterprise-specific traps and notifications, an event consumer must define classes in the CIM repository by compiling MIB definitions using the SNMP MIB compiler (such as that made for the Cisco device to retrieve private MIB information about the memory flash but related to traps or notifications).

  • Enterprise nonspecific: These traps do not correspond to any of the generic event types or enterprise-specific event types. Nonenterprise-specific traps and notifications do not have their MIB definitions compiled into the SMIR. These traps are listed in Table 3.68.

We can use the Cisco router to show how to capture traps sent by the device at startup. To monitor SNMP traps, we will reuse Sample 6.17 ("A generic script for asynchronous event notification") in the appendix). This would generate the following result:

  1:   C:\>GenericEventAsyncConsumer.wsf "Select * From SnmpColdStartNotification                                                                          Where AgentAddress='10.10.10.253'" /Namespace:Root\SNMP\CiscoBrussel  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:   Waiting for events...  6:  7:   BEGIN - OnObjectReady.  8:   Saturday, 02 February, 2002 at 16:05:16: 'SnmpColdStartNotification' has been triggered.  9: 10:     - SnmpColdStartNotification ----------------------------------------------------- 11:     AgentAddress: .......................... 10.10.10.253 12:     AgentTransportAddress: ................. 10.10.10.253 13:     AgentTransportProtocol: ................ IP 14:     Community: ............................. public 15:     Identification: ........................ 1.3.6.1.6.3.1.1.5.1 16:     TIME_CREATED: .......................... 02-02-2002 15:05:16 (20020202150516.010497+060) 17:     TimeStamp: ............................. 1096 18: 19:   END - OnObjectReady. 20: 21:   BEGIN - OnObjectReady. 22:   Saturday, 02 February, 2002 at 16:05:18: 'SnmpColdStartNotification' has been triggered. 23: 24:   - SnmpColdStartNotification ----------------------------------------------------- 25:   AgentAddress: .......................... 10.10.10.253 26:   AgentTransportAddress: ................. 10.10.10.253 27:   AgentTransportProtocol: ................ IP 28:   Community: ............................. public 29:   Identification: ........................ 1.3.6.1.6.3.1.1.5.1 30:   TIME_CREATED: .......................... 02-02-2002 15:05:18 (20020202150518.010497+060) 31:   TimeStamp: ............................. 1096 32: 33:   END - OnObjectReady. 

Since the purpose is to receive traps related to the device startup, the WQL event query uses the SnmpColdStartNotification event class. We see in the previous output sample that the Cisco device sends two traps (lines 7 through 19 and lines 21 through 33). Because the SnmpColdStartNotification class is a generic trap representation coming from RFC 1215, we get the strict minimum information about the Cisco device itself. The dotted number contained in the Identification property (line 29) is the OID number used by the SNMP trap coldStart.

To get the SNMP trap-specific information without searching for the corresponding Cisco MIB (enterprise-specific traps), we can use a trick. This trick is not the ideal solution (the ideal solution will be the use of the specific Cisco MIB file), but when we must deal with a device for which very little information is available, this work-around can save a lot of time while giving a fairly usable solution. For this we must modify a definition made in the CIM repository in the Root\SNMP\SMIR namespace and enhance a portion of the script code.

In the Root\SNMP\SMIR namespace, there is a class called the NotificationMapper class. This class has several instances that correspond to the SNMP event standard classes. As we can see in Figure 3.49, among several instances, we have an instance with the OID number 1.3.6.1.6.3.1.1.5.1 in correspondence with the SnmpColdStartNotification event class.

click to expand
Figure 3.49: The NotificationMapper instances.

If a trap is received by WMI for which there is no corresponding SNMP event class for the received OID number, then WMI triggers an extrinsic event with the SnmpVINotification or SnmpV2Notification event class. This corresponds to an enterprise nonspecific trap. If we delete the instance using the OID number 1.3.6.1.6.3.1.1.5.1, then WMI will not be able to map the received trap to the generic SnmpColdStartNotification event class. In such a case, as explained, WMI will map the trap to the SnmpVINotification or SnmpV2Notification event class. Now, if we take a closer look at the SnmpVINotification or SnmpV2Notification classes (Figure 3.50), we see the VarBindList property, which is an array of SnmpVarBind objects.

click to expand
Figure 3.50: The SnmpV2Notification class and the varBindList property.

The SnmpVarBind class is shown in Figure 3.51.

click to expand
Figure 3.51: The SnmpVarBind class is an array of object instances.

As we can see, this class exposes three properties, called Encoding, ObjectIdentifier, and Value, where the Value property is an array of integers. This is an important detail and we will see how to read this information when examining Sample 3.75.

Now that the NotificationMapper instance using the OID number 1.3.6.1.6.3.1.1.5.1 is deleted and before examining the code, let's see the result when the Cisco router sends the same traps as before (coldStart).

  1:   C:\>GenericEventAsyncConsumer.wsf "Select * From SnmpV2Notification                                                                          Where AgentAddress='10.10.10.253'" /Namespace:Root\SNMP\CiscoBrussels  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:   Waiting for events...  6:  7:   BEGIN - OnObjectReady.  8:   Saturday, 02 February, 2002 at 17:47:38: 'SnmpV2Notification' has been triggered.  9:     AgentAddress (wbemCimtypeString) = 10.10.10.253 10:     AgentTransportAddress (wbemCimtypeString) = 10.10.10.253 11:     AgentTransportProtocol (wbemCimtypeString) = IP 12:     Community (wbemCimtypeString) = public 13:     Identification (wbemCimtypeString) = 1.3.6.1.6.3.1.1.5.1 14:     SECURITY_DESCRIPTOR (wbemCimtypeUint8) = (null) 15:     TIME_CREATED (wbemCimtypeUint64) = 02-02-2002 16:47:38 (20020202164738.823428+060) 16:     TimeStamp (wbemCimtypeUint32) = 1096 17:     1.3.6.1.2.1.1.3.0 (TimeTicks) = 1095 18:     1.3.6.1.4.1.9.2.1.2.0 (OCTET STRING) = reload 19:     1.3.6.1.3.1057.1 (IpAddress) = 10.10.10.253 20:     1.3.6.1.6.3.1.1.4.3.0 (OBJECT IDENTIFIER) = 1.3.6.1.4.1.9.1.19 21: 22:   END - OnObjectReady. 23: 24:   BEGIN - OnObjectReady. 25:   Saturday, 02 February, 2002 at 17:47:39: 'SnmpV2Notification' has been triggered. 26:     AgentAddress (wbemCimtypeString) = 10.10.10.253 27:     AgentTransportAddress (wbemCimtypeString) = 10.10.10.253 28:     AgentTransportProtocol (wbemCimtypeString) = IP 29:     Community (wbemCimtypeString) = public 30:     Identification (wbemCimtypeString) = 1.3.6.1.6.3.1.1.5.1 31:     SECURITY_DESCRIPTOR (wbemCimtypeUint8) = (null) 32:     TIME_CREATED (wbemCimtypeUint64) = 02-02-2002 16:47:39 (20020202164739.013702+060) 33:     TimeStamp (wbemCimtypeUint32) = 1100 34:     1.3.6.1.2.1.1.3.0 (TimeTicks) = 1099 35:     1.3.6.1.4.1.9.2.1.2.0 (OCTET STRING) = reload 36:     1.3.6.1.3.1057.1 (IpAddress) = 10.10.10.253 37:     1.3.6.1.6.3.1.1.4.3.0 (OBJECT IDENTIFIER) = 1.3.6.1.4.1.9.1.19 38: 39:   END - OnObjectReady. 

The result now displays the information contained in the SnmpVarBind instances, which are themselves contained in the varBindList array made of a collection of instances. For example, at lines 18 and 35, we see the OID number 1.3.6.1.4.1.9.2.1.2.0. This number corresponds to specific Cisco private MIB information. If you examine the Cisco documentation, you will discover that this SNMP information shows the reason for the last device reboot. In this case, since we used the Cisco reload command, we see the text "reload" (lines 18 and 35). To translate Cisco MIB OID numbers to a readable form (1.3.6.1.4.1.9.2.1.2.0 to whyReload), you can also use the following URL: http://jaguar.ir.miami.edu/%7Emarcus/snmptrans.html.

The script we use to display this information is still Sample 6.17 ("A generic script for asynchronous event notification") in the appendix. However, at line 112 (see the following extract), this script invokes the DisplayProperties() function from the sink routine (the DisplayProperties() function is available in Sample 4.30, "A generic routine to display the SWbemPropertySet object" in the appendix).

   1:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  10:  11:    <?job error="True" debug="True" ?>  12:  13:    <runtime>  ..:  19:    </runtime>  20:  21:    <script language="VBScript" src="/books/2/679/1/html/2/.\Functions\DisplayInstanceProperties (With SNMP).vbs" />  22:    <script language="VBScript" src="/books/2/679/1/html/2/.\Functions\TinyErrorHandler.vbs" />  23:    <script language="VBScript" src="/books/2/679/1/html/2/.\Functions\PauseScript.vbs" />  24:  25:    <object prog  reference="true"/>  26:    <object prog  />  27:  28:    <script language="VBscript">  29:    <![CDATA[  ..:  33:    ' -----------------------------------------------------------------------------------------  34:    Const cComputerName = "LocalHost"  35:    Const cWMINameSpace = "Root/cimv2" ...: 103:    ' ----------------------------------------------------------------------------------------- 104:    Sub SINK_OnObjectReady (objWbemObject, objWbemAsyncContext) 105: 106:        Wscript.Echo 107:        Wscript.Echo "BEGIN - OnObjectReady." 108:        WScript.Echo FormatDateTime(Date, vbLongDate) & " at " & _ 109:                     FormatDateTime(Time, vbLongTime) & ": '" & _ 110:                     objWbemObject.Path_.Class & "' has been triggered." 111: 112:        DisplayProperties objWbemObject, 2 113:        Wscript.Echo 114: 115:        Wscript.Echo "END - OnObjectReady." 116: 117:    End Sub 118: ...: 127: 128:    ]]> 129:   </script> 130:  </job> 131:</package> 

To display the SnmpVarBind instances, we updated the DisplayProperties() function accordingly. The code is shown in Sample 3.74. The code of this updated subroutine starts as the original one (lines 14 through 30). The only change made in the DisplayProperties() function concerns the test of the property name (line 31) and the invocation of the DisplaySNMPBindings() function (line 32), if the property is the VarBindList property exposed by the SnmpV1Notification or SnmpV2Notification classes.

Sample 3.74: The updated DisplayProperties() function to display the SnmpVarBind instances

start example

  .:  6:' ---------------------------------------------------------------------------------------------  7:Function DisplayProperties (objWMIInstance, intIndent) ..: 14:    Set objWMIPropertySet = objWMIInstance.Properties_ 15:    For Each objWMIProperty In objWMIPropertySet 16: 17:        boolCIMKey = objWMIProperty.Qualifiers_.Item("key").Value 18:        If Err.Number Then 19:           Err.Clear 20:            boolCIMKey = False 21:        End If 22:        If boolCIMKey Then 23:           strCIMKey = "*" 24:        Else 25:           strCIMKey = "" 26:        End If 27: 28:        If Not IsNull (objWMIProperty.Value) Then 29:           If objWMIProperty.CIMType = wbemCimtypeObject Then 30:              If objWMIProperty.IsArray Then 31:                 If objWMIProperty.Name = "VarBindList" Then 32:                     DisplaySNMPBindings objWMIProperty, intIndent 33:                 Else 34:                     For Each varElement In objWMIProperty.Value 35:                         WScript.Echo Space (intIndent) & strCIMKey & objWMIProperty.Name & _ 36:                                      " (" & GetCIMSyntaxText (objWMIProperty.CIMType) & ")" 37:                         DisplayProperties varElement, intIndent + 2 38:                     Next 39:                 End If 40:              Else 41:                 WScript.Echo Space (intIndent) & strCIMKey & objWMIProperty.Name & _ 42:                              " (" & GetCIMSyntaxText (objWMIProperty.CIMType) & ")" 43:                 DisplayProperties objWMIProperty.Value, intIndent + 2 44:              End If 45:           Else ..: 75:           End If 76:        Else ..: 79:        End If 80:    Next ..: 83:End Function 84: ..: ..: ..: 

end example

Next, if the property matches the varBindList property, Sample 3.75, which contains the DisplaySNMPBindings() function, is executed.

Sample 3.75: The DisplaySNMPBindings() function to display the SnmpVarBind instances

start example

  ..:  ..:  ..:  84:  85:' ---------------------------------------------------------------------------------------------  86:Function DisplaySNMPBindings (varBindList, intIndent)  ..:  96:    For Each varBindElement In varBindList.Value  97:        Set objWMIPropertySet = varBindElement.Properties_  98:  99:        varSNMPValue = "" 100: 101:        For Each objWMIProperty In objWMIPropertySet 102:            Select Case objWMIProperty.Name 103:                   Case "Encoding" 104:                        strSNMPEncoding = objWMIProperty.Value 105: 106:                   Case "ObjectIdentifier" 107:                        strSNMPOID = objWMIProperty.Value 108: 109:                   Case "Value" 110:                        Select Case strSNMPEncoding 111:                               Case "TimeTicks" 112:                                    varSNMPValue = objWMIProperty.Value(0) + _ 113:                                      objWMIProperty.Value(1) * 256 + _ 114:                                      objWMIProperty.Value(2) * 256 * 256 + _ 115:                                      objWMIProperty.Value(3) * 256 * 256 * 256 116:                               Case "INTEGER" 117:                                    varSNMPValue = objWMIProperty.Value(0) + _ 118:                                      objWMIProperty.Value(1) * 256 + _ 119:                                      objWMIProperty.Value(2) * 256 * 256 + _ 120:                                      objWMIProperty.Value(3) * 256 * 256 * 256 121:                               Case "OCTET STRING" 122:                                    For Each varElement In objWMIProperty.Value 123:                                        varSNMPValue = varSNMPValue & Chr(varElement) 124:                                    Next 125:                               Case "IpAddress" 126:                                    For Each varElement In objWMIProperty.Value 127:                                        If Len (varSNMPValue) = 0 Then 128:                                           varSNMPValue = varElement 129:                                        Else 130:                                           varSNMPValue = varSNMPValue & "." & varElement 131:                                        End If 132:                                    Next 133:                               Case "OBJECT IDENTIFIER" 134:                                    For intIndice=0 to Ubound (objWMIProperty.Value) Step 4 135:                                        varElement = objWMIProperty.Value(0 + intIndice) + _ 136:                                          objWMIProperty.Value(1 + intIndice) * 256 + _ 137:                                          objWMIProperty.Value(2 + intIndice) * 256 * 256 + _ 138:                                          objWMIProperty.Value(3 + intIndice) * 256 * 256 * 256 139:                                        If Len (varSNMPValue) = 0 Then 140:                                           varSNMPValue = varElement 141:                                        Else 142:                                           varSNMPValue = varSNMPValue & "." & varElement 143:                                        End If 144:                                    Next 145:                               Case Else 146:                                    varSNMPValue "<unknown coding>" 147: 148:                        End Select 149: 150:                   Case Else 151: 152:            End Select 153:        Next 154:        Set objWMIPropertySet = Nothing 155: 156:        WScript.Echo strSNMPOID & " (" & strSNMPEncoding &") = "& varSNMPValue 157: 158:    Next 159: 160:End Function ...: ...: ...: 

end example

Because the VarBindList property is an array, the values of this property are enumerated (lines 96 through 158). Next, since each of these values is an object made from the SnmpVarBind class, the script extracts the properties of the examined SnmpVarBind instance (line 97). As we have done many times now, each property is enumerated in a loop for further examination (lines 101 through 153). Based on the property name of the SnmpVarBind instance (line 102), the value of the property is retrieved accordingly (lines 103, 106, and 109). To retrieve the value of the Value property, some special care must be taken. Because the SnmpVarBind, properties enumeration retrieves the encoding type of the Value property from the Encoding property (line 104), the script uses an appropriate decoding technique based on the value of the Encoding property (lines 110 through 148). Four encoding types are considered:

  • TIMETICKS: The TIMETICKS encoding is a value made up of 4 bytes. Lines 112 through 115 calculate the corresponding value.

  • INTEGER: The INTEGER encoding is an integer. Lines 117 through 120 calculate the corresponding value.

  • OCTET STRING: The OCTET STRING is an array of bytes. Lines 112 through 124 concatenate each byte of the array in one single string.

  • IpAddress: The IpAddress is an array of bytes. Lines 126 through 131 concatenate each byte of the array in one single dotted string to represent a well-formatted IP address.

  • OBJECT IDENTIFIER: The OBJECT IDENTIFIER is an array of bytes, where each 4 bytes represent an integer. Lines 134 through 144 calculate the value of the integer and concatenate each value in one single dotted string to represent a well-formatted OID number.

Once the value extraction and formatting are completed, the script displays the SNMP information in a readable form (line 156).

3.7.5.5 Sending SNMP commands

If it is possible to read SNMP data from an SNMP-enabled device, it is also possible to write some information via SNMP. Of course, the device managed with SNMP must support a set of SNMP commands. Again, we need the SNMP knowledge and information available from the device itself. For example, with the Cisco router we used in the previous examples, it is possible to send an SNMP command to reload the device. Of course, the router must be configured properly at the SNMP level to accept such a command for obvious security reasons. Figure 3.43 ("Enabling SNMP on your Cisco router") shows the Cisco router SNMP configuration to access the device via SNMP. However, in order to make the Cisco router accept an SNMP reload command, it is necessary to add the following statements:

 1:   snmp-server community private RW 2:   snmp-server system-shutdown 

Line 1 is already part of the configuration shown in Figure 3.43 and defines the community string for SNMP write operations. However, line 2 is mandatory to reboot the Cisco router via SNMP. Of course, the primary goal is not to demonstrate how to reboot active network devices via SNMP but to show how, from a script written on top of WMI, it is possible to send an SNMP command to an SNMP-enabled device, where the SNMP command is defined in a private MIB of a manufacturer. The overall principle will always be the same despite the device used.

First of all, because the Reboot command is defined in a private MIB of Cisco, it is necessary to convert the desired MIB to a MOF file. The SNMP reload command definition is defined in the OLD-CISCO-TS-MIB.My MIB. This MIB, similar to the one we used previously, is also available from the Cisco Web site. As we did previously, the MIB file must be converted to a MOF file with the following command line:

 C:\>smi2smir /g OLD-CISCO-TS-MIB.My CISCO-SMI.my > OLD-CISCO-TS-MIB.Mof 

Next, in order to make this SNMP information available to WMI, the generated MOF file must be loaded in the CIM repository with MOFCOMP.EXE:

 C:\>MOFCOMP OLD-CISCO-TS-MIB.Mof Microsoft (R) 32-bit MOF Compiler Version 5.1.3590.0 Copyright (c) Microsoft Corp. 1997-2001. All rights reserved. Parsing MOF file: OLD-CISCO-TS-MIB.Mof MOF file has been successfully parsed Storing data in the repository... Done! 

Figure 3.52 shows the WMI class result obtained from the private MIB conversion.

click to expand
Figure 3.52: The SNMP_OLD_CISCO_TS_MIB_lts class to send SNMP commands to a Cisco device (SNMP-enabled).

The SNMP class to send SNMP commands to the device is called SNMP_OLD_CISCO_TS_MIB_lts. This class exposes a property called tsMsgSend. Basically, by looking at the MIB file, the tsMsgSend supports four parameters:

 tsMsgSend OBJECT-TYPE     SYNTAX  INTEGER {          nothing(1),          reload(2),          messagedone(3),          abort(4)     )     ACCESS read-write     STATUS mandatory     DESCRIPTION             "Sends the message. The value determines what             to do after the message has completed."     ::= { lts 9 } 

These parameters are also shown in the MOF file generated from the SMI2SMIR.EXE conversion or from WMI CIM Studio by looking at the enumeration qualifier (see Figure 3.53). The interesting parameter for our purpose is the Reload parameter.

click to expand
Figure 3.53: The tsMsgSend property qualifiers.

Of course, it must be clear that a perfect knowledge of the SNMP capabilities of the device is a requirement to find out which information to use to perform the desired management tasks. As mentioned previously, you must refer to your device manufacturer if you need support to locate the desired information.

How to proceed? In theory, the goal is simple: A script must create an instance of the SNMP_OLD_CISCO_TS_MIB_lts class and store the "Reload" value into the tsMsgSend property. Next, the script will commit the updated instance back to the CIM repository. The end result will create an SNMP write operation to the corresponding MIB property, which will reload the Cisco router. In practice, things are less simple, since some details must be taken into consideration, especially when saving the updated instance back to the CIM repository. The logic is implemented in Sample 3.76.

Sample 3.76: Sending SNMP commands

start example

  1: <?xml version="1.0"?>  .:  8: <package>  9:  <job> ..: 13:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" /> 14: 15:    <object prog  reference="true"/> 16:    <object prog  /> 17: 18:    <script language="VBscript"> 19:    <![CDATA[ ..: 23:    Const cComputerName = "LocalHost" 24:    Const cWMINameSpace = "Root/SNMP/CiscoBrussels" 25:    Const cWMIClass = "SNMP_OLD_CISCO_TS_MIB_lts" ..: 33:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 34:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 35:    Set objWMIServices = objWMILocator.ConnectServer(cComputerName, cWMINameSpace, "", "") ..: 38:    objWMINamedValueSet.Add "Correlate", True 39:    objWMINamedValueSet.Add "AgentAddress", "Cisco-Brussels.LissWare.Net" 40:    objWMINamedValueSet.Add "AgentFlowControlWindowSize", 3 41:    objWMINamedValueSet.Add "AgentReadCommunityName", "public" 42:    objWMINamedValueSet.Add "AgentRetryCount", 1 43:    objWMINamedValueSet.Add "AgentRetryTimeout", 500 44:    objWMINamedValueSet.Add "AgentVarBindsPerPdu", 10 45:    objWMINamedValueSet.Add "AgentWriteCommunityName", "private" 46: 47:    Set objWMISNMPInstance = objWMIServices.Get(cWMIClass & "=@") ..: 50:    objWMISNMPInstance.tsMsgSend = "Reload" 51: 52:    objWMINamedValueSet.Add "__PUT_EXTENSIONS", True 53:    objWMINamedValueSet.Add "__PUT_EXT_CLIENT_REQUEST", True 54:    objWMINamedValueSet.Add "__PUT_EXT_PROPERTIES", Array ("tsMsgSend") 55: 56:    objWMISNMPInstance.Put_ wbemChangeFlagUpdateOnly Or wbemFlagReturnWhenComplete, _ 57:                            objWMINamedValueSet 58:    If Err.Number Then 59:       WScript.Echo "0x" & Hex(Err.Number) & " - " & Err.Description & vbCRLF 60: 61:       Set objWMILastError = CreateObject("wbemscripting.swbemlasterror") 62:       WScript.Echo "Description: " & objWMILastError.Description 63:       WScript.Echo "Operation: " & objWMILastError.Operation 64:       WScript.Echo "ParameterInfo: " & objWMILastError.ParameterInfo 65:       WScript.Echo "ProviderName: " & objWMILastError.ProviderName 66:       WScript.Echo "SnmpStatusCode: 0x" & Hex (objWMILastError.SnmpStatusCode) 67:       WScript.Echo "StatusCode: 0x " & Hex(objWMILastError.StatusCode) 68:       WScript.Echo "Operation: " & objWMILastError.Operation 69:       WScript.Echo "ParameterInfo: " & objWMILastError.ParameterInfo 70:       WScript.Echo "ProviderName: " & objWMILastError.ProviderName ..: 73:       WScript.Quit (1) 74:    End If 75: 76:    WScript.Echo "Cisco router successfully reloaded." ..: 81:    ]]> 82:    </script> 83:  </job> 84:</package> 

end example

From line 33 through 35, Sample 3.76 executes the WMI connection to the CIM repository. Next, from line 38 through 45, it sets up an SWBemNamedValueSet object defining the SNMP connection parameters (as shown in Sample 3.71). Note the assignment of the AgentWriteCommunityName property (line 45) with a valid community string to perform an SNMP write operation. Next, the SNMP_OLD_CISCO_TS_MIB_lts instance is created (line 47) and the "Reload" value is assigned to the tsMsgSendproperty (line 50). The important and interesting point concerns the scripting technique used to save the updated instance back to the CIM repository (lines 52 through 57). This technique uses the partial-instance update technique previously used in section 3.6.1.1, "Creating and updating objects in Active Directory." It is mandatory to commit the change in this way to the CIM repository, because only the tsMsgSend property must be written. Note that trying to save the complete instance to the CIM repository will make the Put_ method invocation fail. If an SNMP error occurs, it is possible to retrieve some extra information by using the SWbemLastError object, discussed in Chapter 5 of the first book, Understanding WMI Scripting. For example, if the statement "snmp-server system-shutdown" is omitted in the Cisco configuration, the error returned will be as follows:

  1:   C:\>ReloadCisco.Wsf  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:   0x80041001 - Generic failure  6:  7:   Description: Agent reported Bad Value for property 'tsMsgSend'  8:   Operation: PutInstance  9:   ParameterInfo: 10:   ProviderName: MS_SNMP_INSTANCE_PROVIDER 11:   SnmpStatusCode: 0x80041030 12:   StatusCode: 0x80041001 13:   Operation: PutInstance 14:   ParameterInfo: 15:   ProviderName: MS_SNMP_INSTANCE_PROVIDER 

If everything is properly set up, the SNMP command will be sent to the Cisco device, which will be reloaded. Note that the Cisco router sends an SNMP trap after receiving this SNMP command. It is always possible to enhance Sample 3.76 to capture the SNMP trap message confirming the successful reload of the router.

3.7.5.6 Debugging SNMP providers

In the previous example we saw that the SWbemLastError object provides some extra information about the last WMI error. However, when working with SNMP devices, it is not always easy to troubleshoot the installation to determine the cause of the problem. A nice feature coming with the WMI SNMP implementation is the ability to trace the SNMP provider activity. Basically, the tracing activity setup is the same as the Active Directory providers' tracing activity. It uses the same registry key values (see Table 3.53, "Enabling the Trace Logging of a WMI Provider") but in a different registry hive:

 HKLM\SOFTWARE\Microsoft\WBEM\PROVIDERS\Logging\WBEMSNMP 

The value to use for the Level registry key takes an integer value from 0 through 2^32 - 1. The value is a logical mask consisting of 32 bits. Table 3.71 shows the bit masks to define the type of debugging output to be generated. By default, the information is contained in the SWBEMSNMP.LOG file.

Table 3.71: The SNMP Debugging Output Level

Bits

Description

0

SNMP class provider SWbemServices object method invocations

1

SNMP class provider implementation

2

SNMP instance provider SWbemServices object method invocations

3

SNMP instance provider implementation

4

SNMP class library

5

SNMP SMIR

6

SNMP correlator

7

SNMP type mapping code

8

SNMP threading code

9

SNMP event provider interfaces and implementation

With a Level value of 35 when executing Sample 3.76 ("Sending SNMP commands"), the resulting trace is as follows:

  1: CImpClasProv::GetObjectAsync ( (SNMP_OLD_CISCO_TS_MIB_lts) )  2: SnmpClassGetAsyncEventObject :: SnmpClassGetAsyncEventObject ()  3: SnmpClassGetAsyncEventObject :: Process ()  4: SnmpClassGetEventObject :: ProcessClass ( WbemSnmpErrorObject &a_errorObject )  5: SnmpClassGetAsyncEventObject :: ReceiveClass ( IWbemClassObject *classObject )  6: Returning from SnmpClassGetEventObject :: ProcessClass ( WbemSnmpErrorObject &a_errorObject (0))  7: SnmpClassGetAsyncEventObject :: ReceiveComplete ()  8: Reaping Task  9: Deleting (this) 10: Returning from SnmpClassGetAsyncEventObject :: Receive4 () 11: Returning from SnmpClassGetAsyncEventObject :: Process () 12: WbemSnmpErrorObject :: SetMessage ( () ) 13: SnmpClassGetAsyncEventObject :: -SnmpClassGetAsyncEventObject () 14: Sending Status 15: Returning from SnmpClassGetAsyncEventObject :: -SnmpClassGetAsyncEventObject () 16: Returning from CImpClasProv::GetObjectAsync ( (SNMP_OLD_CISCO_TS_MIB_lts) ) with Result = (0) 




Leveraging WMI Scripting
Leveraging WMI Scripting: Using Windows Management Instrumentation to Solve Windows Management Problems (HP Technologies)
ISBN: 1555582990
EAN: 2147483647
Year: 2003
Pages: 82
Authors: Alain Lissoir

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net