« The Relevance of Relevance | Main | Doonesbury Mentions Blogging »

August 30, 2005

Monad and WMI

Abhishek did talk about the get-wmiobject cmdlet on the team blog, but I wanted to expand on it a bit more.

The basic use of the cmdlet is what you would expect:

MSH> get-wmiobject Win32_BIOS
SMBIOSBIOSVersion : Version 1.10
Manufacturer : TOSHIBA
Name : v1.10
[...]

But the command can do much more than that. WMI queries are built with WQL, a SQL-like query language. They look just like SQL queries, of the form:

select PROPERTY from CLASS where FILTER

and get-wmiobject surfaces those through the -property, -class, and -filter parameters. -class is a positional parameter, in position 0, so the previous command was actually:

MSH> get-wmiobject -class Win32_BIOS

You can use -property and -class as you would expect (I'm not going to include the output because I'm lazy, but trust me it works):

MSH> get-wmiobject Win32_LogicalDisk -property DeviceId,DriveType
MSH> get-wmiobject Win32_LogicalDisk -filter "DriveType = 3"

But because the objects that get-wmiobject outputs can be accessed like anything else in Monad, you can instead do these as:

MSH> get-wmiobject Win32_LogicalDisk | select-object DeviceId,DriveType
MSH> get-wmiobject Win32_LogicalDisk | where-object { $_.DriveType -eq 3 }

(Filtering via select-object instead of get-wmiobject -property actually gives slightly different output. There are property sets defined for many WMI objects in the default types.mshxml files (search for "Win32_" in the file to see them), which controls the set of properties displayed; for some reason when you use -property it changes the type name slightly in the output objects, which causes it to display more properties. I'm not sure if this is a bug or by design).

Now you might think the following would work:

MSH> get-wmiobject Win32_NetworkAdapterConfiguration -filter "IpEnabled = True and IpAddress != '0.0.0.0'"

but it doesn't, because IpAddress returned by WMI is actually an array, and WQL doesn't handle arrays. Luckily MSH can filter that just fine, since -ne of a scalar vs. an array is true if the scalar is not in the array:

MSH> get-wmiobject Win32_NetworkAdapterConfiguration | where-object { $_.IpEnabled -and $_.IpAddress -ne "0.0.0.0" }

But you can get even fancier if you have the proper WMI steez...WMI namespaces have a class called "meta_class" which lists all classes in a namespace. And WQL has an ISA operator which can test for class inheritance. You can do any WQL query if you remember how the get-wmiobject parameters map to the WQL select statement. So a statement like:

select __class from meta_class where __this isa 'Win32_CurrentTime'

becomes

MSH> get-wmiobject meta_class -filter "__this isa 'Win32_CurrentTime'" | select-object __class

which will return Win32_CurrentTime, Win32_LocalTime, and Win32_UTCTime (I'm using select-object instead of get-wmiobject -property because of the formatting issue I mentioned above).

You can also use the -namespace parameter to search other namespaces beyond the default (which is "root\cimv2"); I won't get too into details, but if you want to explore, the command

MSH> get-wmiobject -namespace "root" -class "__namespace" | select-object Name

will return all the child namespaces of "root", and you can then investigate further with commands like:

MSH> get-wmiobject -namespace "root\WMI" -class meta_class | select-object __class

Posted by AdamBa at August 30, 2005 09:16 AM

Trackback Pings

TrackBack URL for this entry:
http://proudlyserving.com/cgi-bin/mt-tb.cgi/303

Comments

The reason using the -property filter changes the output display properties is because the type is constructed using the __namespace property. Normally that property is included automatically but if you specify -property then it only uses that list so __namespace is not included (unless you ask for it).

So the solution is to say -property DeviceId,DriveType,__namespace. Then it can construct the type that matches what is in types.mshxml, so it displays the default property set. This means it includes all the fields (like FreeSpace) that didn't select, with no values shown (which you may not like, but that's how the formatter works so it's a separate issue). At least you don't get all the __ properties displayed.

Compare:

MSH C:\> get-wmiobject Win32_logicaldisk -filter "deviceid='c:'"

DeviceID : C:
DriveType : 3
ProviderName :
FreeSpace : 22845833216
Size : 73402363904
VolumeName :


MSH C:\> get-wmiobject Win32_logicaldisk -filter "deviceid='c:'" -property deviceid,drivetype

DeviceID : C:
DriveType : 3
__GENUS : 2
__CLASS : Win32_LogicalDisk
__SUPERCLASS :
__DYNASTY :
__RELPATH : Win32_LogicalDisk.DeviceID="C:"
__PROPERTY_COUNT : 2
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :


MSH C:\> get-wmiobject Win32_logicaldisk -filter "deviceid='c:'" -property deviceid,drivetype,__namespace

DeviceID : C:
DriveType : 3
ProviderName :
FreeSpace :
Size :
VolumeName :


MSH C:\> get-wmiobject Win32_logicaldisk -filter "deviceid='c:'" | select-object deviceid,drivetype

deviceid drivetype
-------- ---------
C: 3


- adam

Posted by: Adam Barr at September 2, 2005 09:26 AM

monad looks nice. seems to be something of an object-oriented shell. that is a very cool idea.

Posted by: jeremiah at September 4, 2005 08:30 AM