Hyper-V WMI Using PowerShell Scripts – Part 3
Published Mar 21 2019 12:56 PM 1,188 Views
Brass Contributor
First published on TECHNET on May 06, 2008
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 rootvirtualization -Query "Select * From Msvm_ComputerSystem Where ElementName='Server 2008 - Test1'"
$Kvp = Get-WmiObject -Namespace rootvirtualization -Query "Associators of {$Vm} Where AssocClass=Msvm_SystemDevice ResultClass=Msvm_KvpExchangeComponent"


$Kvp.GuestIntrinsicExchangeItems | Import-CimXml





Output of the WMIKVP.ps1 Script



PS C:> . 'D:BlogsDemopowerShellDemoWMIKVP.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

sc_project=3725534; sc_invisible=1; sc_partition=45; sc_security="9a688012";

Version history
Last update:
‎Mar 21 2019 12:56 PM
Updated by: