Tip: Correlating WMI queries

A question came up in another venue about correlating two WMI queries. That query was related to a custom hardware WMI provider for battery life checking, but provides a good example for several other areas.

Suppose there are two different WMI classes that are related in some way. In my test case, I used the “Win32_NetworkAdapter” and “Win32_NetworkAdapterConfiguration” classes. Suppose there was a need to retrieve “Name” from Win32_NetworkAdapter, and to also retrieve “DHCPServer” from the matching Win32_NetworkAdapterConfiguration. We can observe that both classes have an “InterfaceIndex” property that matches between the two classes:

Win32_NetworkAdapter:

q: selects "Name, InterfaceIndex, PnPDeviceID from Win32_NetworkAdapter" of wmi
A: InterfaceIndex=5
A: Name=Microsoft Kernel Debug Network Adapter
A: PNPDeviceID=ROOT\KDNIC\0000
A: InterfaceIndex=12
A: Name=Intel(R) 82579LM Gigabit Network Connection
A: PNPDeviceID=PCI\VEN_8086&DEV_1502&SUBSYS_1589103C&REV_05\3&11583659&A&C8
A: InterfaceIndex=2
A: Name=Broadcom NetXtreme Gigabit Ethernet
A: PNPDeviceID=PCI\VEN_14E4&DEV_1681&SUBSYS_168114E4&REV_10\4&800FF6A&0&00E6
A: InterfaceIndex=11

And Win32_NetworkAdapterConfiguration:

q: selects "InterfaceIndex,DHCPServer from Win32_NetworkAdapterConfiguration " of wmi 
A: DHCPServer
A: InterfaceIndex=5
A: DHCPServer=192.168.1.1
A: InterfaceIndex=12
A: DHCPServer
A: InterfaceIndex=2
A: DHCPServer
A: InterfaceIndex=11

Using the selects "<query>" of wmi syntax that’s commonly used in examples here, it is very difficult to correlate these values. This is because every property from each query comes back as a separate result, rather than as multiple properties for each instance.

The advice I’d give is to switch to the less commonly-used select objects "<query>" of wmi :

q: properties whose (it as string contains "wmi object")
A: property <string> of <wmi object>: wmi select
A: select objects <string> of <wmi>: wmi object
A: properties of <wmi object>: wmi select

Using this syntax, we can select each instance and retrieve tuple results for properties that are linked to each object:

q: (string values of properties "Name" of it, string values of properties "InterfaceIndex" of it) of select objects "Name,InterfaceIndex from Win32_NetworkAdapter" of wmi
A: Microsoft Kernel Debug Network Adapter, 5
A: Intel(R) 82579LM Gigabit Network Connection, 12
A: Broadcom NetXtreme Gigabit Ethernet, 2

q: (string value of property "InterfaceIndex" of it, string values of properties "DHCPServer" of it) of select objects "DHCPServer,InterfaceIndex from Win32_NetworkAdapterConfiguration" of wmi
A: 12, 192.168.1.1

Now that we can retrieve each query as tuple results, we can treat the queries themselves as tuples, and filter to matching InterfaceIndex values:

q: (string value of property "InterfaceIndex" of item 0 of it, string value of property "Name" of item 1 of it, string values of properties "DHCPServer" of item 0 of it) of (select objects "DHCPServer,InterfaceIndex from Win32_NetworkAdapterConfiguration" of wmi, select objects "Name,InterfaceIndex,PnPDeviceID from Win32_NetworkAdapter" of wmi) whose (string value of property "InterfaceIndex" of item 0 of it = string value of property "InterfaceIndex" of item 1 of it)
A: 12, Intel(R) 82579LM Gigabit Network Connection, 192.168.1.1

This should be applicable in several areas, for instance matching up an installed driver version to the PnPDeviceID of the enumerated devices or (as in the original case for which this came up) getting distinct battery charge levels where there are multiple batteries in the machine and the current charge and full charge values are provided in separate classes.

5 Likes