How to Build a Hyper-V Performance Monitoring Tool with PowerShell

#requires -version 5.0

#requires -runasAdministrator

#requires -module Hyper-V

#use max of 3 VMS in the console. You may also need to resize the console window.

#use max of 4 VMs in the ISE

#Show-MemoryPressureProgress

Function Show-VMMemoryPressure {

    [cmdletbinding(DefaultParameterSetName = “interval”)]

    Param(

        [Parameter(Position = 0, Mandatory, HelpMessage = “Enter the name of a virtual machine.”)]

        [alias(“Name”)]

        [string[]]$VMName,

        [Parameter(HelpMessage = “The name of the Hyper-V Host”)]

        [Alias(“CN”, “vmhost”)]

        [string]$Computername = $env:computername,

        [Parameter(HelpMessage = “The sample interval in seconds”)]

        [int32]$Interval = 5,

        [Parameter(HelpMessage = “The maximum number of samples”, ParameterSetName = “interval”)]

        [ValidateScript( {$_ -gt 0})]

        [int32]$MaxSamples = 2,

        [Parameter(HelpMessage = “Take continuous measurements.”, ParameterSetName = “continous”)]

        [switch]$Continuous,

        [switch]$ClearHost

    )

    DynamicParam {

        if ($host.name -eq ‘ConsoleHost’) {

            #define a collection for attributes

            $attributes = New-Object System.Management.Automation.ParameterAttribute

            $attributes.Mandatory = $False

            $attributes.HelpMessage = “Enter a console color”

            $attributeCollection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]

            $attributeCollection.Add($attributes)

            #define the dynamic param

            $dynParam1 = New-Object -Type System.Management.Automation.RuntimeDefinedParameter(“ProgressBackground”, [system.consolecolor], $attributeCollection)

            $dynParam1.Value = $host.PrivateData.ProgressBackgroundColor

            #define the dynamic param

            $dynParam2 = New-Object -Type System.Management.Automation.RuntimeDefinedParameter(“ProgressForeground”, [system.consolecolor], $attributeCollection)

            $dynParam2.Value = $host.PrivateData.ProgressForegroundColor

            #create array of dynamic parameters

            $paramDictionary = New-Object -Type System.Management.Automation.RuntimeDefinedParameterDictionary

            $paramDictionary.Add(“ProgressBackground”, $dynParam1)

            $paramDictionary.Add(“ProgressForeground”, $dynParam2)

            #use the array

            return $paramDictionary

        } #if consolehost

    } #close DynamicParam

    Begin {

        $counters = @()

        $vmhash = @{}

        $j = 0

        if ($ClearHost) {

            Clear-Host

        }

        

        #limit number of VMs

        if ($host.name -eq ‘ConsoleHost’) {

            $max = 3

            if ($PSBoundParameters.ContainsKey(“ProgressBackground”)) {

                $savedbg = $host.PrivateData.ProgressBackgroundColor

                 $host.PrivateData.ProgressBackgroundColor = $PSBoundParameters.ProgressBackground

                  Write-Verbose “Using progress background color $ProgressBackground”

            }

            if ($PSBoundParameters.ContainsKey(“ProgressForeground”)) {

                $savedfg = $host.PrivateData.ProgressForegroundColor

                $host.PrivateData.ProgressForegroundColor = $PSBoundParameters.ProgressForeground

                Write-Verbose “Using progress foreground color $Progressforeground”

            }          

        }

        elseif ($host.name -match “ISE”) {

            $max = 4

        }

    } #begin

    Process {

        foreach ($item in $VMName[0..($max 1)]) {

            Try {

                Write-Verbose “Verifying $item on $Computername”

                $vm = Get-VM -ComputerName $computername -Name $item -ErrorAction stop

                if ($vm.state -ne ‘running’) {

                    $msg = “The VM {0} on {1} is not running. Its current state is {2}.” -f $item.Toupper(), $Computername, $vm.state

                    Write-Warning $msg

                }

                else {

                    Write-Verbose “Adding VM data”

                    $counters += “Hyper-V Dynamic Memory VM($($vm.vmname))Average Pressure”

                    #create a hash with VMNames and a number for their progress id

                    $j++

                    $Vmhash.Add($vm.vmname, $j)

                }

            } #Try

            Catch {

                Write-Warning $_.exception.message

            } #Catch

        } #foreach item

        if ($counters.count -gt 0) {

            $counterparams = @{

                Counter          = $counters

                ComputerName     = $Computername

                SampleInterval   = $Interval

                pipelinevariable = “pv”

            }

            if ($Continuous) {

                $counterparams.Add(“Continuous”, $True)

            }

            else {

                $counterparams.Add(“MaxSamples”, $MaxSamples)

            }

            Write-Verbose “Getting counter data”

            $counterparams | Out-String | Write-Verbose

            Get-Counter @counterparams | ForEach-Object {

                $_.countersamples | Sort-Object -property Instancename |

                    Group-Object -property instancename | ForEach-Object {

                    #scale values over 100

                    $pct = ($_.group.cookedvalue) * .8

                    #if scaled value is over 100 then max out the percentage

                    if ($pct -gt 100) {

                        $pct = 100

                    }

                    $progparams = @{

                        Activity         = $_.Name.ToUpper()

                        Status           = $($pv.Timestamp)

                        CurrentOperation = “Average Pressure: $($_.group.cookedvalue)”

                        PercentComplete  = $pct

                        id               = $vmhash[$_.Name]

                    }

                    Write-Progress @progparams

                } #for each value

            } #foreach countersample

        } #if counters

    } #process

    End {

        #set private data values back

        if ($savedbg) {

            $host.PrivateData.ProgressBackgroundColor = $savedbg

        }

        if ($savedfg) {

            $host.PrivateData.ProgressForegroundColor = $savedfg

        }

    } #end

} #close function

Go to Original Article
Author: Jeffery Hicks