Hyper-V WMI Using PowerShell Scripts – Part 3 (KVP's - Guest OS Version)
Update 12/5/12
A lot has changed since 2008 and many things have stayed the same… I wanted to provide an update to some of the most commonly viewed posts and this was one of them.
For updated information on this topic please refer to my latest post Retrieving the IP Address Of A VM In Hyper-V .
Original Post
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
Comments
Anonymous
July 06, 2008
The comment has been removedAnonymous
September 21, 2008
How to retrieve the volume information of the guest system?Anonymous
September 21, 2008
How to retrieve the volume information of the guest system? =========================================
Gordon,
We don't have an inbox method of querying guest volume/storage information from the host or querying host volume/storage information from the guest. You could howerver use the KVP IC to write your own. -TaylorAnonymous
February 09, 2009
Is it possible to create the virtual machines programatically and them run a post install config script on each at initial logon? I need to create (weekly) a large number of like-configured machines and I'd rather not do it manually. Thanks CHAnonymous
July 16, 2011
The comment has been removedAnonymous
October 16, 2014
Thank you Taylor.. I was looking for the same thing over past few days..! :) though there's a little problem..with this solution, cause when i tried to run this script on my hyper -v server with a few Linux OS's . it did not fetch me OSname, OSversion ...and a bunch of other details..!! Can you suggest me any improvements to get this script working in this scenario ?? Thanks in advance..Anonymous
March 17, 2015
Hi, I am looking for a whey to push a command to a VM in Hyper-v that got no network and get results outside. Like "ping localhost" and see the results. Can KVP help in this issue? Is there any other powershell script that can do that? Thanks