October 30th, 2011

Use WMI Association Classes to Relate Two Classes Together

Doctor Scripto
Scripter

Summary: Use a cool Windows PowerShell technique to easily relate two WMI classes together.

 

Microsoft Scripting Guy Ed Wilson here. Well, the Scripting Wife and I are getting settled back down from our Canadian tour. We had a great time visiting MVPs on our return. We got to see Jeffery Hicks in Syracuse, Joel Bennett in Rochester, and Ken McFerron in Pittsburgh, Pennsylvania. While teaching my Windows PowerShell class in Montreal, I realized that I had not written very much about using Windows PowerShell with WMI association classes.

When querying a WMI association class, the results return references to external classes. In fact, the things that are returned point to the key property of the referenced classes. An example will help to clarify this. My laptop has a network adapter. The win32_networkadapter WMI class describes the maker, the speed, MAC address, and other information about my network adapter. The following query returns information about my network adapter:

gwmi win32_networkadapter -Filter “netconnectionid = ‘local area connection'”

If I want to find all of the information about my network adapter, but I do not want to see any empty properties (because some WMI classes contain literally hundreds of properties many of which do not return any information), I use the haswmivalue filter from my WMI module.

In the following figure, I use the haswmivalue filter from my HSGWMImoduleV5 module to return all the properties that contain a value. (Of course, the haswmivalue function also exists in HSGWMImoduleV6 as well. Version six of my HSG WMI Module is the latest version, and it includes several upgrades to version five).

Image of using haswmivalue filter

In addition to having physical information, such as the MAC address and speed, a network adapter also has a protocol (or more than one protocol) bound to it. To find protocol type of information, such as the TCP/IP address, subnet mask, and default gateway, it is necessary to query the Win32_NetworkAdapterConfiguration WMI class. To make matters worse, the netconnectionid property that I used when querying the Win32_NetworkAdapter WMI class is not available. In addition, the key property from Win32_NetworkAdapter is DeviceID, but the key property from Win32_NetworkAdapterConfiguration is index. Upon closer observation, however, this problem is not as bad as it might seem. Using my Get-WmiKeyValue function from my HSGWmiModuleV6 WMI module, I can easily see that the properties from the two different WMI classes are probably related (the values seem to be identical). This is shown in the following figure.

Image showing that properties from the two WMI classes are probably related

From my previous query of Win32_NetworkAdapter, I saw that the deviceID of 7 was the network interface from which I wanted to obtain information. Using this value as the index number, I come up with the following query (gwmi is an alias for Get-WmiObject). The first position is class and I left it out. The f stands for filter and I was able to use the abbreviation. The haswmivalue filter is from my WMI module.

gwmi win32_networkadapterconfiguration -F “index = 7” | HasWmiValue

The command and associated output are shown in the following figure.

Image of command and associated output

What is needed is a way to query both WMI classes at the same time. I need to see both the hardware information and the protocol related information for the same adapter. There is a solution for this problem; I can use an association WMI class. In the old VBScript days, querying a WMI association class was a really hard-core task that few outside of the Microsoft Scripting Guys really understood. This can all change in the Windows PowerShell world, because querying WMI association classes is trivial. Keep in mind that there are more than 100 association classes in root\cimv2 alone. These classes expose very useful and powerful information about your system.

Using my Get-WmiClassesWithQualifiers function from my WMI module, I can easily find association classes in any WMI namespace. For our purposes, I will focus on association classes in Root\CimV2 (the default WMI namespace.) I am only interested in working with dynamic WMI classes, and unfortunately, I did not add a dynamic filter to my Get-WmiClassesWithQualifiers function (this is something I will probably do at a later date). In the meantime, I can reduce the number of WMI classes I need to filter through by removing the classes that begin with cim. In most cases, classes that begin with cim are abstract classes. I use the following query to find association classes in Root\CimV2.

Get-WMIClassesWithQualifiers -qualifier association | ? { $_ -notmatch ‘^cim’} | sort

The command and associated output are shown in the following figure.

Image of command and associated output

Exploration of these association classes will yield fruitful and profitable results. To illustrate working with these classes, I want to examine the Win32_NetworkAdapterSetting association class. This class relates the two WMI classes we began with: Win32_NetworkAdapter and Win32_NetworkAdapterConfiguration.

The first thing I do is query the Win32_NetworkAdapterSetting WMI class directly by using the Get-WMIObject cmdlet. This query is shown here (using the gwmi alias for Get-WmiObject):

gwmi win32_networkadaptersetting

The command and associated output are shown in the following figure.

Image of command and associated output

A close examination of both the element and the setting properties reveals they point to the key properties of the Win32_NetworkAdapter and Win32_NetworkAdapterConfiguration WMI classes. It is possible to filter out using WQL, but it starts to get tricky, and it is therefore easier to use the Where-Object cmdlet to find an element that has the deviceID of 7 (the value we found earlier). This is really easy to do, and the command is shown here (I use gwmi for Get-WmiObject and ? for Where-Alias):

gwmi win32_networkadaptersetting | ? {$_.element -match 7}

The [WMI] management accelerator accepts this fully qualified path to a management object, and will return the associated class. To query these, I first store the result from the previous command into a variable called $adapter. Next, I use the [WMI] type accelerator to return the specific WMI instance of my Win32_NetworkAdapter and my Win32_NetworkAdapterConfiguration classes. Here are the three commands:

$adapter = gwmi win32_networkadaptersetting | ? {$_.element -match 7}

[wmi]$adapter.Element | HasWmiValue

[wmi]$adapter.Setting | HasWmiValue

The following figure illustrates these three commands and the associated output.

Image of three commands and associated output

One other thing before I go. It is possible to perform a less direct filter. This is because using the [WMI] type accelerator and the path, I obtain a complete instance of the WMI class that is referenced. This means I can use the same type of query that I used previously with Get-WMIObject when querying the WMI classes directly. Perhaps an example will suffice. In the following code, I use the Get-WMIObject (gwmi is the alias) to query the Win32_NetworkAdapterSetting WMI class. I use the where-object cmdlet (? is the alias) to perform my filtering. I already know that the first command, gwmi win32_networkadaptersetting, returns a collection of paths that point to the key values of all instances of Win32_NetworkAdapter and Win32_NetworkAdapterConfiguration. I choose the value stored in the element property because it points to instances of Win32_NetworkAdapter. I can therefore use one of my favorite techniques that I call “group and dot” where I group the results by using parentheses, and I access a specific property by using dotted notation. After I have the specific property, I look for elements that have a value of the netconnectionid property that will match local area connection. The command is shown here:

gwmi win32_networkadaptersetting | ? {([wmi]$_.element).netconnectionID -match ‘local area connection’}

The command and associated output are shown in the following figure.

Image of command and associated output

Well, that is all there is to working with WMI association classes. Hopefully, you will search for other association classes using the techniques I have outlined here, and then you will also begin to explore the type of information that is available.

 

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

 

 

Author

The "Scripting Guys" is a historical title passed from scripter to scripter. The current revision has morphed into our good friend Doctor Scripto who has been with us since the very beginning.

0 comments

Discussion are closed.