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 (7)

  1. I have gotten a ton of questions about the KVP Exchange or Data Exchange Integration Component… 

  2. Gordon Zhou says:

    How to retrieve the volume information of the guest system?  

  3. Gordon Zhou says:

    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.

    -Taylor

  4. CH says:

    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

    CH

  5. TM says:

    Hi,

    Quote

    "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 "

    Can we use kvps to set and retrieve subnet mask and gateway of a network adapter inside a VM in Hyper? Can u share how it could be done??? I was able to retrive IP addresses (ipv4 and ipv6) via kvp but was unable to get DNS address , subnet mask, gateway wins address and other network adapter properties. A post on getting this information from a virtual machine in Hyper V could help. Sample code in C# would be huge favor.

    Hope to see a reply/post soon.

    Thanks

  6. Henry says:

    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..

  7. Erez says:

    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