Previous Section Table of Contents Next Section

Understanding WMI Relationships

Probably the best way to understand the more complex WMI classes is with an example. Take Win32_NetworkAdapter. This class represents a physical network adapter inside a computer, whether it's an Ethernet adapter, an IEEE 1394 (FireWire) adapter, or whatever. If you examine the class' properties in the WMI documentation, you'll see that it only includes properties that deal with the physical hardware, such as its MAC address, whether it supports media sense (which tells Windows that a cable is unplugged), its maximum speed, and so forth.

WMI also defines a class named Win32_NetworkAdapterConfiguration, which includes the software aspects of a network adapter, including its IP address, IPX settings, and so forth. In theory, a single hardware adapter can have multiple possible configurations, which is why these properties are split into two classes. In fact, it's theoretically possible for one configuration to be shared by two different physical adapters. WMI needs some way to relate the two classes to one another, and that way is called an associator class. In this case, the associator class is Win32_NetworkAdapterSetting, which associates a network adapter and its configuration settings.

An examination of Win32_NetworkAdapterSetting's documentation reveals that it has only two properties: Win32_NetworkAdapter and Win32_ NetworkAdapterConfiguration. In other words, the two properties refer back to the associated classes. The associator, then, represents a single combination of adapter and configuration, as illustrated in Figure 19.1.

Figure 19.1. Associating two classes

graphics/19fig01.gif

You'll notice that neither the Scriptomatic nor the PrimalScript WMI Query Wizard includes Win32_NetworkAdapterSetting on their list of classes. That's because neither tool is designed to deal with associator classes, so you are on your own for working with them. You can get a bit of help from the Wbemtest tool, however. (I showed you how to use Wbemtest in Chapter 17.)

First, run Wbemtest and connect to your local computer's root\cimv2 namespace. Then, click Open Class and open the Win32_ NetworkAdapterSetting class. You should see a dialog box like the one in Figure 19.2. Of particular interest are the two main properties: Element and Setting. According to the WMI documentation, this class' Element represents a Win32_NetworkAdapter, and the Setting represents an associated Win32_NetworkAdapterConfiguration.

Figure 19.2. Examining the Win32_NetworkAdapterSetting class

graphics/19fig02.gif

Click Instances to retrieve all instances of this class. The dialog box that appears lists one line for each combination of adapter and configuration. You'll notice that the Element property is listed as something like "\\\\computername\\root\\cimv2:Win32_NetworkAdapter.DeviceID=\"1\"." The Setting property will look something like "\\\\computername\\root\\cimv2:Win32_NetworkAdapterConfiguration.Index=1." Here's how to interpret that.

  • First, understand that both backslashes and double quotes are illegal characters for WMI. The backslash is actually an escape character, meaning it's used to prefix illegal characters. So \\ should be interpreted as a single backslash, and \" should be interpreted as a single quote.

  • The first part of each property value is the namespace: \\computername\root\cimv2. The property's value derives from this namespace.

  • The next part of each property value is the class name, followed by a period and the property name.

  • The property name is followed by an equal sign, and then the associated property value.

In this example, the Element represents the instance of Win32_NetworkAdapter with the DeviceID of 1, and the Setting represents the instance of Win32_NetworkAdapterConfiguration with the Index of 1.

A quick-and-dirty way to query this information would be something like the following.


Dim oWMI, oSettings, oSetting

Dim oAdapter, oConfig



'connect to WMI

Set oWMI = GetObject("winmgmts:\\.\root\cimv2")



'retrieve all settings

Set oSettings = oWMI.ExecQuery( _

 "SELECT * FROM Win32_NetworkAdapterSetting")



'go through all settings

For Each oSetting in oSettings



 'get the element

 Set oAdapter = GetObject("winmgmts:" & _

  oSetting.Element)

 WScript.Echo "Adapter: " & oAdapter.Caption



 'get the setting

 Set oConfig = GetObject("winmgmts:" & _

  oSetting.Setting)

 WScript.Echo "   DHCP: " & oConfig.DHCPEnabled



 'print a divider

 WScript.Echo String(20,"-")



Next

This script uses a WQL query to retrieve all instances of Win32_NetworkAdapterSetting. Because each Element and Setting property is a complete WMI path, they are used to retrieve the appropriate Win32_NetworkAdapter and Win32_NetworkAdapterConfiguration classes. The script then prints one piece of information from each class, just to prove it's doing something. This is a standardized way that you can work with associator classes.

  • Retrieve the associator class

  • Use its properties, such as Element and Setting in this example, to retrieve the associated classes.

  • Work with the associated classes however you like.

Not all associator classes use Element and Setting. For example, Win32_PrinterShare associates a local printer and a network share, from Win32_Printer and Win32_Share. Win32_PrinterShare uses Antecedent to refer to a Win32_Printer instance, and Dependent to refer to a Win32_Share class, instead of Element and Setting. However, you can query the associator class and its associations in exactly the same way.


Dim oWMI, oPShares, oPShare

Dim oPrinter, oShare



'connect to WMI

Set oWMI = GetObject("winmgmts:\\.\root\cimv2")



'retrieve all settings

Set oPShares = oWMI.ExecQuery( _

 "SELECT * FROM Win32_PrinterShare")



'go through all settings

For Each oPShare in oPShares



 'get the element

 Set oPrinter = GetObject("winmgmts:" & _

  oPShare.Antecedent)

 WScript.Echo "Printer: " & oPrinter.Name



 'get the setting

 Set oShare = GetObject("winmgmts:" & _

  oPShare.Dependent)

 WScript.Echo "  Share: " & oShare.Name



 'print a divider

 WScript.Echo String(20,"-")



Next

Note that all I've done in this case is change the variable names and property names. The structure of this example is identical to the first.

    Previous Section Table of Contents Next Section