Monday, June 11, 2007

WMI Collection or Instance?

I was working with WMI in PowerShell today trying to get some disk data from a cluster, and I ran into an odd behavior that had me stumped for a while. Here’s a simplified version of the problem (this is not what I was doing with the cluster, but the WMI behavior is identical). I got a WMI object with the intent of using an associator class to get related information. In this example, I get a Win32_LogicalDisk instance and try to relate it to Win32_DiskPartition. I used the following commands:

PS C:\> $z=gwmi win32_logicaldisk -filter "DeviceID='C:'"
PS C:\> $y=$z.psbase.GetRelated("Win32_DiskPartition")
PS C:\> $y.name
PS C:\>
Notice that $y.name was NULL. But if I looked at the whole value, there was one instance:
PS C:\> $y

NumberOfBlocks : 75504448
BootPartition : True
Name : Disk #0, Partition #0
PrimaryPartition : True
Size : 38658277376
Index : 0
What the heck? Why couldn’t I get the value of a property? Well, it turns out that even though GetRelated() returned only one instance, what came back was actually a collection:
PS C:\> $y.gettype().FullName
System.Management.ManagementObjectCollection
What made it work was forcing $y to be a scalar. By wrapping the statement in $(), I was able to get this as a single instance as opposed to a one-instance collection:
PS C:> $($y).name
Disk #0, Partition #0
Alternatively, this can be accomplished at assignment with the following:
PS C:\> $y=$($z.psbase.GetRelated("Win32_DiskPartition"))
PS C:\> $y.name
Disk #0, Partition #0
The above applies in general to the GetRelated() method. Regardless of the number of instances returned (even zero), the object returned is always a System.Management.ManagementObjectCollection and must always be treated as a collection.

No comments: