Automating Windows System Health Reporting in N‑central with WinSAT and PowerShell

Have you ever had that one computer at a specific customer that always seems broken? If you've ever looked at ticket metrics, you might find these devices poking their heads up. We all have them. Devices that are likely under-specced, abused, or neglected. Over the years I've had the opportunity to build scripts that give time back into the company and add value to customers. One of my favorite scripts takes already built-in reporting on Windows devices and turns it into a monitorable service within N-central. Moving us from a reactive style of support to proactive.

WinSAT: A Forgotten Tool or a Hidden Gem?

Back when Windows Vista was making its debut, Microsoft tucked in a lesser-known tool called the Windows System Assessment Tool (WinSAT). It didn’t get much fanfare, and like many utilities that ship with Windows, it mostly flew under the radar. But if you know where to look, it’s actually a pretty handy way to gauge hardware performance.

WinSAT was developed in the early 2000s as part of Microsoft’s push to better understand how different PC components stacked up. The result was the Windows Experience Index. That numerical score you used to see, rating things like your CPU, RAM, graphics card, and storage. It wasn’t meant to measure reliability, but it did give users and administrators a consistent way to size up a machine’s performance.

In this script, WinSAT is just the beginning. We also hook into Windows’ Reliability Monitor to grab the system’s Stability Index — a value pulled from the Win32_ReliabilityStabilityMetrics class. That number reflects how stable the machine has been lately, based on crash reports, hardware hiccups, and sudden shutdowns. When combined with performance scores, it paints a much clearer picture: not just how fast a device is, but how well it’s holding up over time.

Prerequisites

  • Windows PowerShell 5.1 or later
  • The WinSAT feature installed (built into most Windows builds)
  • Elevated (Administrator) session
  • N-central agents deployed

Script Breakdown

The two steps of the script will be to run a formal WinSAT assessment, retrieving CPUScore, MemoryScore, GraphicsScore, D3DScore, DiskScore, and BaseScore. The BaseScore is actually the lowest score out of all the metrics compiled. However, for this script I wanted to capture each individual score so I can better understand what scored high and those important things that scored low. Typically the score for these metrics goes from 0.0 to 9.9.

# 1. Run WinSAT assessment
Write-Host "Running WinSAT Formal assessment..." -ForegroundColor Cyan
Start-Process winsat -ArgumentList formal -WindowStyle Hidden -Wait

# 2. Grab WinSAT scores
$ws = Get-CimInstance Win32_WinSat

The third step is to pull the latest SystemStabilityIndex from ReliabilityStabilityMetrics. This index measures the overall stability of Windows over time. Typically ranging from 1-10, tracks frequency and severity of system crashes, errors, and downtime.

# 3. Pull the latest Stability Index
$rel = Get-CimInstance Win32_ReliabilityStabilityMetrics |
       Sort-Object TimeGenerated -Descending |
       Select-Object -First 1

The fourth step is to pull in total uptime and unexpected shutdowns over the past 30 days. These are typically the low-hanging fruit when troubleshooting issues so I wanted to make sure I can easily track these separately in the same script.

# 4. Calculate uptime & shutdowns
$os = Get-CimInstance Win32_OperatingSystem
$uptimeDays = ([int]((Get-Date) - $os.LastBootUpTime).TotalDays)
$shutdowns30d = (Get-WinEvent -FilterHashtable @{
    LogName   = 'System'
    Id        = 41
    StartTime = (Get-Date).AddDays(-30)
}).Count

Although the Stability index already takes into account event logs that are critical, it's important to keep track of critical event logs both in System and Application logs. This provides us an early warning just in case the Stability index hasn't dropped in score.

# 5. Count critical events in the last 30 days
$since = (Get-Date).AddDays(-30)
$critSys = (Get-WinEvent -FilterHashtable @{ LogName='System'; Level=1; StartTime=$since }).Count
$critApp = (Get-WinEvent -FilterHashtable @{ LogName='Application'; Level=1; StartTime=$since }).Count

Finally, we need to put all of the results into a single object so we can output the results both to an N-central Custom Service and output to stdout.

# 6. Build a typed PSCustomObject
$report = [PSCustomObject]@{
    CPUScore               = [double]$ws.CPUScore
    MemoryScore            = [double]$ws.MemoryScore
    GraphicsScore          = [double]$ws.GraphicsScore
    D3DScore               = [double]$ws.D3DScore
    DiskScore              = [double]$ws.DiskScore
    BaseScore              = [double]$ws.WinSPRLevel
    StabilityIndex         = [double]$rel.SystemStabilityIndex
    UptimeDays             = $uptimeDays
    UnexpectedShutdowns30d = $shutdowns30d
    CriticalSysEvents30d   = $critSys
    CriticalAppEvents30d   = $critApp
}

# 7. Output each metric for N‑central AMP
$outCPUScore = $report.CPUScore
$outMemoryScore = $report.MemoryScore
$outGraphicsScore = $report.GraphicsScore
$outThreeDScore = $report.D3DScore
$outDiskScore = $report.DiskScore
$outBaseScore = $report.BaseScore
$outStabilityIndex = $report.StabilityIndex
$outUptimeDays = $report.UptimeDays
$outUnexpectedShutdowns = $report.UnexpectedShutdowns30d
$outCriticalSysEvents = $report.CriticalSysEvents30d
$outCriticalAppEvents = $report.CriticalAppEvents30d

$report

This script along with a pre-built AMP and service template export can be found on our Github

Importing the Script into N-central

  1. Log in to your N-central instance and navigate to the Service Organization Level (purple).
  2. On the left-hand navigation, go to Configuration -> Monitoring -> Service Templates
  3. At the top of the page you'll see the Import button, click it
  4. You'll then want to import the three service templates provided in the GitHub repo
  5. Finally, you can build a custom rule for these templates or incorporate them into existing rules

You should see the service on the devices targeted by your rule. Below is an example of the custom service Custom Health Score Service

Related Posts

SSL/TLS Certificate Automation

Last time, we talked about how SSL/TLS certificates are getting shorter and shorter, with lifespans potentially dropping to just 47 days by 2029. Sounds like a headache, right? Who wants to manually r...

Read More