rojo
rojo

Reputation: 24476

Primitive values of WMI classes

This is a complicated idea, and I hope you'll bear with me as its articulation is difficult.

It seems that some WMI classes have a primitive value that can be queried, while others do not. This has practical significance.

Demo 1

Take, for instance, the Win32_Processor class. Its primitive value, as far as I can tell, is the value of its instance's DeviceID column. This allows querying, for example, the architecture (32 / 64-bitness) of the running OS with a tidy one-liner, like this JScript example:

var arch = GetObject("winmgmts:root\\cimv2:Win32_Processor='cpu0'").AddressWidth

In that example, GetObject acts as a sort of select instance where primitive value="cpu0" and returns a single instance, rather than a collection. This works as intended.

Demo 2

On the other hand, the Win32_OperatingSystem class has no primitive value that I've been able to find. Like the Win32_Processor class DeviceID column, the MSDN documentation for Win32_OperatingSystem claims that the CreationClassName column is the table's key field.

Assume that predictably, CreationClassName=="Win32_OperatingSystem". Therefore, one might infer that a similar one-liner could be written thusly:

var arch = GetObject("winmgmts:root\\cimv2:Win32_OperatingSystem='Win32_OperatingSystem'").OSArchitecture

However, that results in an error. My trial-and-error attempts at using other column values have equally all met with failure. Appending .columname between the classname and = results in a syntax error as well.

As far as I can tell, there's no way to identify a single instance of the Win32_OperatingSystem class without enumerating all instances, even if there is only one instance to enumerate.

var wmi = GetObject("winmgmts:");
var os = wmi.ExecQuery("select OSArchitecture from Win32_OperatingSystem");
for (var res = new Enumerator(os); !res.atEnd(); res.moveNext()) {
    var arch = res.item().OSArchitecture;
}

These lines can be combined somewhat:

var os = GetObject("winmgmts:").ExecQuery("select OSArchitecture from Win32_OperatingSystem");
var arch = new Enumerator(os).item().OSArchitecture;

... but it'd still be nice to query an instance directly within Win32_OperatingSystem without having to enumerate an irritatingly vestigial hierarchy.

The question

How can I predict whether a WMI class has a primitive value that can be queried, and which column contains that value?

Upvotes: 3

Views: 376

Answers (2)

Shay Levy
Shay Levy

Reputation: 126842

What you're looking for is the 'Key' property.

http://blogs.msdn.com/b/powershell/archive/2008/04/15/wmi-object-identifiers-and-keys.aspx

Upvotes: 2

rojo
rojo

Reputation: 24476

In powershell, the Get-WmiObject cmdlet (or gwmi alias) provides some insight that isn't obvious or readily available in MSDN. When querying classes via gwmi there are some differences among classes that are either not well or not at all documented elsewhere (or at least not easily searchable). Take the following powershell session for example:

enter image description here

You see the Win32_Processor class has __RELPATH and __PATH properties which refer to the class's primitive value of CPU0; whereas the Win32_OperatingSystem class has no such properties.

That could be a strong hint to help determine whether the class you wish to query must be fully enumerated before it can be parsed.

Upvotes: 1

Related Questions