patpitchaya - Fotolia

Get started Bring yourself up to speed with our introductory content.

Build a PowerShell performance monitoring script step by step

Admins familiar with PowerShell can bypass a third-party server monitoring tool and instead write scripts to track key performance metrics. Learn how with this tutorial.

The ability to monitor server performance is critical for IT administrators. It's extremely important to understand servers' performance levels to eliminate potential problems.

While there are many third-party server monitoring tools, PowerShell also provides this capability -- though, it takes some time and patience on behalf of admins.

Decide what to monitor

Before creating a PowerShell performance monitoring script, determine what to monitor. PowerShell can track several metrics, known as performance counters. In this article, we'll build a script to monitor the performance counters below. To get these performance counters, use the Get-Counter cmdlet.

  • (*)% Idle Time
  • (*). Disk sec/Read
  • (*). Disk sec/Write
  • (*)Disk Queue Length
  • Bytes/sec
  • Interface(*)Total/sec
  • Interface(*)Queue Length
  • File(*)% Usage

Performance counters form counter sets. Use the ListSet parameter on Get-Counter to find these counter sets, as shown below:

PS> (Get-Counter -ListSet *).CounterSetName | Sort-Object

To view which counters are part of a particular counter set, reference the Counter property. For example, to find all the counters related to storage, locate all counter sets with disk in their name, and view all of the counters inside those counter sets, as shown below:

PS> Get-Counter -ListSet *disk*** | foreach {$_.Counter}

Query performance counters

To further review some code snippets in this article and learn
more about the cmdlet and performance counters outlined
here, check out this session from the PowerShell + DevOps
Global Summit 2019, led by Mike Robbins, a PowerShell expert
and Microsoft Cloud and Datacenter Management MVP.

Once you've defined the counters to query, find the counter samples, which are snapshots of a performance counter value at the time of sampling.

Put the performance counters defined in the last section into an array, and take a single sample of each one to see the value:

$counters = @(
  '\PhysicalDisk(**)\% Idle Time'*
  '\PhysicalDisk(**)\Avg. Disk sec/Read'*
  '\*PhysicalDisk(**)\Avg. Disk sec/Write'
  '\PhysicalDisk(**)\Current Disk Queue Length'*
  '\*Memory\Available Bytes'*
  '\*Network Interface(**)\Bytes Total/sec'
  '\Network Interface(**)\Output Queue Length'*
  '\*Paging File(**)\% Usage'

foreach ($counter in $counters) {
  (Get-Counter -Counter $counter).CounterSamples

The script above will produce an output that looks similar to Figure 1 below. Notice that you have InstanceName and CookedValue properties. Each counter has an instance that indicates the particular entity of that counter that's being monitored. For example, multiple storage volumes could each be an instance, as could multiple network interfaces. Each instance also has a separate value, as displayed under CookedValue.

PowerShell performance monitoring script output
Figure 1. Find performance counter values.

Create an HTML report

To clean up the script output in Figure 1, we can display it in an HTML report. Let's build a basic report that follows a table format and contains the counter category, counter, instance and sample value.

Modify the code from this tutorial to produce the required output:

$samples = foreach ($counter in $counters) {
  $sample = (Get-Counter -Counter $counter).CounterSamples
    Category = $sample.Path.Split('\')[3]
    Counter = $sample.Path.Split('\')[4]
    Instance = $sample.InstanceName
    Value = $sample.CookedValue[0]

The $samples variable will then provide an output that looks like this:

$samples variable output
Figure 2. Output from the $samples variable

Build an HTML page to display this data:

$htmlHeader = @"
  <!doctype html>
  <html lang='en'>

$body = ""

foreach ($sample in $samples) {
  $row = '<tr>'
  foreach ($property in $sample.PSObject.Properties.Name) {
    $row += "<td>$($sample.$property)</td>"
  $row += '</tr>'
  $body += $row
$footer = "</tbody></table></body></html>"
$html = $htmlHeader + $body + $footer
$html | Out-File -FilePath 'C:\ServerPerformance.html' -Force

When the PowerShell performance monitoring script runs, it will output an HTML file that looks similar to the one below in Figure 3. As mentioned above, this report contains the counter category, counter, instance and sample value. Build upon this basic report, as needed.

PowerShell performance script outputs an HTML file
Figure 3. HTML file with PowerShell performance counters

Dig Deeper on Real-Time Performance Monitoring and Management