Hyper-V WMI Using PowerShell Scripts – Part 3
In part 1 we went over basic scripts and tools for gathering some generic information about virtual machines and in part 2 we went over VHD creation and WMI job’s. In part 3 I am going to cover getting more detailed information about a guest operating system by using the KVP Exchange integration component. KVP stands for Key Value Pair this is a service that runs in the guest operating system and allows some limited information to be passed from the guest to the host or parent and vice-verse. For now we are going to focus only on the intrinsic KVP’s these are provided by default on virtual machines that have the integration components installed. The intrinsic KVP’s include: FullyQualifiedDomainName, OsName, OsVersion, CSDVersion, OsMajorVersion, OsMinorVersion, OsBuildNumber, OsPlatformID, ServicePackMajor, SuiteMask, ProductType, ProcessorArhitecture.
I’ll start with the PowerShell script and results and then explain how to decipher each of the KVP’s values but first I want to thank Ed one of our top notch developers that provided me this script...
In the gray box is the body of the script, it’s a bit different then what we have seen in the past primarily because is what looks like a function at the top. This function looking thing is a PowerShell filter, what the filter does is take a bunch of XML known in WMI as an “embedded instance" and converts it into objects. If you want to see the XML in it’s raw form remove the "|Import-CimXml” from the last line of the script and you’ll see how handy this little filter is.
So what’s happening in this script? I will ignore the filter for a moment so the first line is the the $Vm = Get-Wmi… So the first line should look pretty common now, we are getting a Msvm_ComputerSystem WMI object for a given virtual machine “Server 2008 – Test1". The second line is new, we are running an Association query to get a Msvm_KvpExchangeCompoents WMI object for this VM, associations are an optimization in WMI you can think of them like a SQL join statement “Please give me all of the X that corresponds to Y”. The third line is just taking the GuestIntrinsicExchangeItems property of the Msvm_KvpExchangeCompoents and piping or sending it (that’s the | character) to the Import-CimXml filter that’s written above. Now for the filter, so all this filter is doing is using an XML xpath query to go over each “Instance/Property” node and adding it’s name and value to this CimObj object and then returning that object…
WMIKVP.ps1 PowerShell Script
|
filter Import-CimXml { $CimXml = [Xml]$_ $CimObj = New-Object -TypeName System.Object foreach ($CimProperty in $CimXml.SelectNodes("/INSTANCE/PROPERTY")) { $CimObj | Add-Member -MemberType NoteProperty -Name $CimProperty.NAME -Value $CimProperty.VALUE } $CimObj }
$Vm = Get-WmiObject -Namespace root\virtualization -Query "Select * From Msvm_ComputerSystem Where ElementName='Server 2008 - Test1'" $Kvp = Get-WmiObject -Namespace root\virtualization -Query "Associators of {$Vm} Where AssocClass=Msvm_SystemDevice ResultClass=Msvm_KvpExchangeComponent"
$Kvp.GuestIntrinsicExchangeItems | Import-CimXml
|
Output of the WMIKVP.ps1 Script
|
PS C:\> . 'D:\BlogsDemo\powerShell\Demo\WMIKVP.ps1'
Caption : Data : AUTOBVT-M02LJSS Description : ElementName : Name : FullyQualifiedDomainName Source : 2
Caption : Data : Windows Server (R) 2008 Enterprise Description : ElementName : Name : OSName Source : 2
Caption : Data : 6.0.6001 Description : ElementName : Name : OSVersion Source : 2
Caption : Data : Service Pack 1 Description : ElementName : Name : CSDVersion Source : 2
Caption : Data : 6 Description : ElementName : Name : OSMajorVersion Source : 2
Caption : Data : 0 Description : ElementName : Name : OSMinorVersion Source : 2
Caption : Data : 6001 Description : ElementName : Name : OSBuildNumber Source : 2
Caption : Data : 2 Description : ElementName : Name : OSPlatformId Source : 2
Caption : Data : 1 Description : ElementName : Name : ServicePackMajor Source : 2
Caption : Data : 0 Description : ElementName : Name : ServicePackMinor Source : 2
Caption : Data : 274 Description : ElementName : Name : SuiteMask Source : 2
Caption : Data : 3 Description : ElementName : Name : ProductType Source : 2
Caption : Data : 9 Description : ElementName : Name : ProcessorArchitecture Source : 2 |
Ok now how do you decipher all of these values like SuiteMask? All of this data except the fully qualified domain name come from a Windows API GetVersionEx but what you really want to look at is the OSVERSIONINFOEX structure. That documents each of these values, for example SuiteMask has a value of 274 above that's 0x112 and according to the documents that means this guest has: Remote Desktop support, Terminal Services is installed, and it's running an Enterprise SKU of Windows...
There's a lot more you can do with the KVP's such as pushing custom data into the guest from the parent partition/host or providing data from the guest so that the parent partition/host can query it. I can provide samples for this in a future post but only if you want me to - so tell me, actually tell me what posts you want maybe networking or offline vhd servicing or maybe import/export?
--Taylor Brown
--Hyper-V test team
I have been working on virtualization solutions at Microsoft for over 4 years, I started on the team shortly after Microsoft acquired Connectix in 2003. I worked on Virtual Server where I tested a verity of things but focused on networking, serial, and power management. I currently lead the Hyper-V End-to-End team, we are responsible for ensuring the end to end functionality of Hyper-V, this includes working with customers/partners/oem’s/etc… to ensure we are testing and shipping the best quality software possible. I have also worked on the Microsoft 1394 (firewire) team, ACPI (power management) team, and did a brief stent on the Microsoft Smart Watch team as a contractor.