While working on my course for TrainSignal on managing Windows Servers with PowerShell, I came up with an interesting use of the Write-Progress cmdlet. I was working on the performance monitoring lesson and realized I could use Write-Progress as rudimentary graphing tool. The cmdlet has a parameter that lets you specify a value that shows up as the progress bar. Normally we think about moving from 0 to 100, but you can specify any value. So I thought why not pass a performance counter value? After a little work I came up with this demo script.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
The script uses Get-WMIObject to retrieve a performance counter property. My demo needs a property with a value between 1 and 100 because I am using the -PercentComplete parameter with Write-Progress. You could use other types of values but you would need to scale it. You also need to only get a single instance. In my demo I'm querying the Win32_PerfFormattedData_PerfDisk_LogicalDisk class, filtering on drive C: The property I'm checking is PercentDiskTime. I use a simple Get-WMIObject expression to retrieve the value.
[cc lang="PowerShell"]
$stat=get-wmiobject -class $activity -filter $filter -computername $computername -ErrorAction Stop
[/cc]
Then it is simply a matter of using Write-Progress to display it.
[cc lang="PowerShell"]
Write-progress -Activity $activity -status $status -currentoperation $current -PercentComplete $stat.$Property
[/cc]
The script loops for as many times as you want. I have a default of 60. You can also specify the interval between samplings. My demo default is 1 second. Here's what the complete script looks like.
[cc lang="PowerShell"]
<#
.Synopsis
Demo WMI Perf Counter Graph
.Description
This demonstration script uses the Write-Progress cmdlet to display
the value of a WMI Performance counter. Ideally, the counter will
have a value of between 1 and 100. Otherwise you might need to
scale the value.
You must specify a WMI Performance counter. The demo sample is:
Win32_PerfFormattedData_PerfDisk_LogicalDisk
and a filter to limit it to a single instance. The demo filter is:
Name='C:'
Finally, select a property. The demo property is PercentDiskTime.
The demo will check every 1 second (the -Sleep parameter) up to
60 times (the -Maximum parameter).
You can also specify the name of a CSV log file to hold the results.
#>
[cmdletbinding()]
Param(
[Parameter(Position=0)]
[ValidateNotNullorEmpty()]
[string]$Class="Win32_PerfFormattedData_PerfDisk_LogicalDisk",
[Parameter(Position=1)]
[ValidateNotNullorEmpty()]
[string]$Filter="Name='C:'",
[Parameter(Position=2)]
[ValidateNotNullorEmpty()]
[string]$Property="PercentDiskTime",
[string]$Computername=$env:computername,
[int]$Sleep=1,
[int]$Maximum=60,
[string]$Log
)
Write-Verbose ("Querying {0} filter {1} on {2} every {3} second(s) {4} times." -f $class,$filter,$computername,$sleep,$maximum)
#values for Write-Progress
$activity=$class
$status="$Property -> $Filter"
$current=$computername.ToUpper()
Write-Verbose "Graphing the $Property property"
#define an array to hold the results
$results=@()
for ($i=1; $i -le $maximum; $i++) {
Try {
$stat=get-wmiobject -class $activity -filter $filter -computername $computername -ErrorAction Stop
$results+=$stat
Write-progress -Activity $activity -status $status -currentoperation $current -PercentComplete $stat.$Property
sleep -seconds $sleep
}
Catch {
Write-Warning $_.Exception.Message
Return
}
}
if ($Log) {
#export results to a file
Write-Verbose "Exporting results to $log"
$results | export-csv -Path $log
}
Write-Progress -Activity $activity -status "Finished" -Completed
Write-Verbose "Finished"
[/cc]
Because you might want to save results as well I added a parameter so you could specify a file name. The performance data will be exported to a CSV file. Here's a brief video of the script in action.
This is not a fully developed script but rather a demonstration of how you might use this technique.
Download demo-wmiperf-progress and let me know what you think.