Monitoring with PowerShell: user experience issues & Unifi EOL Monitoring

This time I’m tackling two blogs in one go again as both are fairly small and straightforward.

Monitoring user Experience

So I’ve been focussed on a lot of documentation, server, and office365 issues lately and I was kind of ‘forgetting’ to also blog about another key experience indicator users have; their own workstation.

Monitoring workstations is becoming more and more important with the flow of users into cloud environments. Just monitoring RAM, CPU, Disk space, etc is no longer really a thing you should focus on. These days you should be looking more into security monitoring and user experience. I’ve blogged about the Windows Experience Index and Diskspeed before as early indicators something might be wrong.

This time we’re going to delve a little deeper into experience monitoring; specifically application crashes and hangs. Windows has an internal monitoring system for this called the “System Reliability Index”. Each time a application hang, or crash occurs this is logged to the index. We can retrieve this information using PowerShell to report on with our RMM.

Windows Reliability script

$ExpectedIndex = "6.0"
$ExpectedTimetoRun = (get-date).AddDays(-1)
$Metrics = Get-CimInstance -ClassName win32_reliabilitystabilitymetrics | Select-Object -First 1
$Records = Get-CimInstance -ClassName win32_reliabilityRecords | Where-Object { $_.TimeGenerated -gt $Metrics.StartMeasurementDate }

$CombinedMetrics = [PSCustomObject]@{
    SystemStabilityIndex = $Metrics.SystemStabilityIndex
    'Start Date'         = $Metrics.StartMeasurementDate
    'End Date'           = $Metrics.EndMeasurementDate
    'Stability Records'  = $Records

if ($CombinedMetrics.SystemStabilityIndex -lt $ExpectedIndex) { 
    write-host "The system stability index is higher than expected. This computer might not be performing in an optimal state. The following records have been found:"
    $CombinedMetrics.'Stability Records'

if ($CombinedMetrics.'Start Date' -lt $ExpectedTimetoRun) {
    write-host "The system stability index has not been updated since $($CombinedMetrics.'Start Date'). This could indicate an issue with event logging or WMI."

So this script actually helps you out in finding where applications are crashing or hanging often. This should help you localize workstations that are performing poorly and are giving a bad user experience. The great thing is that this also monitors those pesky “Outlook is not responding” issues as these are logged too.

Unifi EOL monitoring

So this one was request by a friend that quickly wanted to find all his unsupported devices for replacement. Replace the URL and credentials with your own and you should be good to go. 🙂

#Find EOL devices
$UnifiBaseUri = "https://yoururl:8443/api"
$UnifiUser = "APIUSER"
$UnifiPassword = "appassword"
$UniFiCredentials = @{
    username = $UnifiUser
    password = $UnifiPassword
    remember = $true
} | ConvertTo-Json
write-host "Logging in to Unifi API." -ForegroundColor Green
try {
    Invoke-RestMethod -Uri "$UnifiBaseUri/login" -Method POST -Body $uniFiCredentials -SessionVariable websession
catch {
    write-host "Failed to log in on the Unifi API. Error was: $($_.Exception.Message)" -ForegroundColor Red
write-host "Collecting sites from Unifi API." -ForegroundColor Green
try {
    $sites = (Invoke-RestMethod -Uri "$UnifiBaseUri/self/sites" -WebSession $websession).data
catch {
    write-host "Failed to collect the sites. Error was: $($_.Exception.Message)" -ForegroundColor Red
$AllDevices = foreach ($site in $sites) {
    $Devices = (Invoke-RestMethod -Uri "$UnifiBaseUri/s/$($" -WebSession $websession).data
    $Devices | Select-Object _id, name, ip, mac, model, type, version, unsupported,@{label = 'site'; expression = { $site.desc } }

$AllDevices | Where-Object { $_.unsupported -ne $false } | Out-GridView

And that’s it! As always, happy PowerShelling!


  1. Ben August 25, 2020 at 8:30 am

    I have got a question regarding the reliability script:
    From my understanding, the higher the SystemStabilityIndex the better. In your script you check wether the current index is greater than our threshold for throwing an error though, which would imply the lower the better. Am I understanding the index wrong?

    1. Kelvin Tegelaar August 25, 2020 at 8:54 am

      Ben, you’re right! I’ll fix it in the blog right now. I changed it during my testing and never flipped it back. Thanks for letting me know!

      1. Ben August 25, 2020 at 9:12 am

        Thanks for making that clear. I would also suggest then to change the Write-Host to “The system stability index is lower than expected.” or something along those lines. Otherwise thanks for the great script!

  2. Remco August 25, 2020 at 9:41 pm

    Hi Kelvin,

    I tried the Windows Reliability script, but nothing happens. Do you have any clue what is going on?
    I am running it in Powershell ISE. No errors or write-hosts are appearing.

    Kind regards,


  3. Pingback: Monitoring with PowerShell: App hangs - CyberDrain

  4. Zach March 18, 2021 at 4:13 pm

    Hey Kelvin,

    Long time follower of your stuff and first off thanks for all your hard work and contributions. I’m using this to identify our EOL devices and just ran it but it only returns 1 device although I show a lot more of devices labeled EOL. Not sure if I’m doing something wrong or not?

  5. Zach Frazier March 18, 2021 at 5:05 pm

    Hey Kelvin,

    I was able to resolve this by just making a list of devices on the EOL list and then making a new filter.

    $EOLDevices = ‘U2S48′,’BZ2′,’U2O’,’U2HSR’,’U2Sv2′,’U7P’,’U2L48′,’U2Lv2′,’U7P’,’U7IWP’,’U7EDU’,’U2IW’
    $AllDevices = foreach ($site in $sites) {
    $Devices = (Invoke-RestMethod -Uri “$UnifiBaseUri/s/$($” -WebSession $websession).data
    $Devices | Select-Object _id, name, ip, mac, model, type, version, unsupported,@{label = ‘site’; expression = { $site.desc }},@{label = ‘EOL’; expression = { $EOLDevices -contains $_.model}}

    $AllDevices | Where-Object {$_.EOL -eq $true} | Out-GridView

  6. Bryan Ard July 23, 2021 at 3:34 pm

    How did you get powershell to accept the self signed certificate?

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.