Skip to content

Instantly share code, notes, and snippets.

@pronichkin
Created March 20, 2021 04:33
Show Gist options
  • Select an option

  • Save pronichkin/ac34cac50afff51d04610a1775b3f9e2 to your computer and use it in GitHub Desktop.

Select an option

Save pronichkin/ac34cac50afff51d04610a1775b3f9e2 to your computer and use it in GitHub Desktop.

Revisions

  1. pronichkin created this gist Mar 20, 2021.
    189 changes: 189 additions & 0 deletions Get-vmGuestExchange.ps1
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,189 @@
    Function
    ConvertFrom-RawXml
    {
    [System.Management.Automation.CmdletBindingAttribute()]
    Param(
    [System.Management.Automation.ParameterAttribute(
    Mandatory = $True
    )]
    [System.String[]]
    $String
    )

    Process
    {
    $Instance = [System.Collections.Generic.List[System.Xml.XmlElement]]::new()

    $xml = [System.Xml.XmlDocument]::new()

    $String | ForEach-Object -Process {
    $xml.LoadXml( $psItem )
    $Instance.Add( $xml.INSTANCE )
    }

    Return $Instance
    }
    }

    Function
    ConvertFrom-XmlInstance
    {
    [System.Management.Automation.CmdletBindingAttribute()]
    Param(
    [System.Management.Automation.ParameterAttribute(
    Mandatory = $True
    )]
    [System.Xml.XmlElement[]]
    $XmlInstance
    )

    Process
    {
    $Property = [System.Collections.Generic.List[
    System.Collections.Generic.Dictionary[
    System.String,
    System.String
    ]
    ]]::new()

    $XmlInstance | ForEach-Object -Process {

    $PropertyCurrent = [System.Collections.Generic.Dictionary[
    System.String,
    System.String
    ]]::new()

    $psItem.Property | ForEach-Object -Process {
    $PropertyCurrent.Add(
    $psItem.Name,
    $psItem.Value
    )
    }

    $Property.Add( $PropertyCurrent )
    }

    Return $Property
    }
    }

    Function
    ConvertFrom-CimProperty
    {
    [System.Management.Automation.CmdletBindingAttribute()]
    Param(
    [System.Management.Automation.ParameterAttribute(
    Mandatory = $True
    )]
    [System.Collections.Generic.List[
    System.Collections.Generic.Dictionary[
    System.String,
    System.String
    ]
    ]]
    $Property
    )

    Process
    {
    $Dictionary = [System.Collections.Generic.Dictionary[
    System.String,
    System.String
    ]]::new()

    $Property | ForEach-Object -Process {

    $Dictionary.Add( $psItem.Name, $psItem.Data )
    }

    Return $Dictionary
    }
    }

    Function
    Get-vmGuestExchange
    {
    [System.Management.Automation.CmdletBindingAttribute()]
    Param(
    [System.Management.Automation.ParameterAttribute(
    Mandatory = $True
    )]
    [Microsoft.HyperV.PowerShell.VirtualMachine[]]
    $vm
    ,
    [System.Management.Automation.ParameterAttribute()]
    [System.Management.Automation.SwitchParameter]
    $Intrinsic
    )

    Process
    {
    $Exchange = [System.Collections.Generic.List[
    System.Collections.Generic.Dictionary[
    System.String,
    System.String
    ]
    ]]::new()

    $vm | ForEach-Object -Process {

    $Filter = "ElementName = '$( $psItem.Name )'"

    $InstanceParam = @{

    CimSession = $psItem.CimSession
    # https://docs.microsoft.com/windows/win32/hyperv_v2/msvm-computersystem
    ClassName = 'msvm_ComputerSystem'
    Namespace = 'root/Virtualization/v2'
    Filter = $Filter
    }
    $ComputerSystem = Get-CimInstance @InstanceParam

    $AssociatedInstanceParam = @{

    InputObject = $ComputerSystem
    # https://docs.microsoft.com/windows/win32/hyperv_v2/msvm-systemdevice
    Association = 'msvm_SystemDevice'
    # https://docs.microsoft.com/windows/win32/hyperv_v2/msvm-kvpexchangecomponent
    ResultClassName = 'msvm_KvpExchangeComponent'
    }
    $KvpExchangeComponent = Get-CimAssociatedInstance @AssociatedInstanceParam

    # Deserialize CIM instances from XML

    If
    (
    $Intrinsic
    )
    {
    $String = $KvpExchangeComponent.GuestIntrinsicExchangeItems
    }
    Else
    {
    $String = $KvpExchangeComponent.GuestExchangeItems
    }

    $Instance = ConvertFrom-RawXml -String $String | Where-Object -FilterScript {
    # https://docs.microsoft.com/windows/win32/hyperv_v2/msvm-kvpexchangedataitem
    $psItem.ClassName -eq 'msvm_KvpExchangeDataItem'
    }

    # Parse instance structure and extract all properties
    $Property = [System.Collections.Generic.List[
    System.Collections.Generic.Dictionary[
    System.String,
    System.String
    ]
    ]]::new()

    ConvertFrom-XmlInstance -XmlInstance $Instance | ForEach-Object -Process {
    $Property.Add( $psItem )
    }

    # Select only the properties we need
    $Exchange.Add( ( ConvertFrom-CimProperty -Property $Property ) )
    }

    Return $Exchange
    }
    }