Created
January 8, 2026 06:09
-
-
Save andyg2/489233f96e4a488513a114aa3ebce5e4 to your computer and use it in GitHub Desktop.
Healthchecks.io Windows Tray Monitor (PowerShell) A lightweight PowerShell script that monitors a Healthchecks.io badge SVG and displays the aggregated status (up, late, down) in the Windows system tray, with notifications on state changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Add-Type -AssemblyName System.Windows.Forms | |
| Add-Type -AssemblyName System.Drawing | |
| # 3 state badge | |
| $badgeUrl = "https://healthchecks.io/badge/37a5b3b3-74a5-43ec-9b65-c1b1b7/2lErRuPC.svg" | |
| $pollSeconds = 10 # Check every 10 seconds | |
| $gracePeriodSeconds = 30 # Must be in a bad state for 30 seconds before notifying (should be >2x multiplier of $pollSeconds) | |
| $notify = New-Object System.Windows.Forms.NotifyIcon | |
| $notify.Icon = [System.Drawing.SystemIcons]::Information | |
| $notify.Visible = $true | |
| $notify.Text = "Healthchecks Aggregate" | |
| $iconOk = [System.Drawing.SystemIcons]::Information | |
| $iconWarn = [System.Drawing.SystemIcons]::Warning | |
| $iconDown = [System.Drawing.SystemIcons]::Error | |
| $lastNotifiedState = "" | |
| $pendingState = "" | |
| $firstDetectedTime = $null | |
| $notify.BalloonTipTitle = "Healthchecks" | |
| $notify.BalloonTipText = "Monitoring started (1m grace period active)" | |
| $notify.ShowBalloonTip(3000) | |
| function Get-BadgeState { | |
| try { | |
| $web = New-Object System.Net.WebClient | |
| $content = $web.DownloadString($badgeUrl) | |
| $regMatches = [regex]::Matches($content, '<text[^>]*>\s*(up|down|late)\s*</text>', 'IgnoreCase') | |
| if ($regMatches.Count -gt 0) { | |
| return $regMatches[$regMatches.Count - 1].Groups[1].Value.ToLower() | |
| } | |
| } | |
| catch { | |
| Write-Host "$(Get-Date) error=$($_.Exception.Message)" | |
| } | |
| return "unknown" | |
| } | |
| while ($true) { | |
| $currentState = Get-BadgeState | |
| # Ignore network blips | |
| if ($currentState -eq "unknown") { | |
| Start-Sleep $pollSeconds | |
| continue | |
| } | |
| if ($currentState -eq $lastNotifiedState) { | |
| # The state matches what we last alerted on. Reset pending timers. | |
| $pendingState = "" | |
| $firstDetectedTime = $null | |
| } | |
| else { | |
| # The state has changed from our last notification | |
| if ($currentState -ne $pendingState) { | |
| # This is the FIRST time we are seeing this specific new state | |
| $pendingState = $currentState | |
| $firstDetectedTime = Get-Date | |
| Write-Host "$(Get-Date) Change detected: $currentState. Waiting for consistency..." | |
| } | |
| else { | |
| # We are currently in the grace period for this state | |
| $elapsed = (New-TimeSpan -Start $firstDetectedTime -End (Get-Date)).TotalSeconds | |
| Write-Host "$(Get-Date) State '$currentState' persistent for $(([math]::Round($elapsed)))s" | |
| if ($elapsed -ge $gracePeriodSeconds) { | |
| # The state has been solid for over a minute. NOTIFY NOW. | |
| Write-Host "$(Get-Date) Grace period exceeded. Updating UI." | |
| switch ($currentState) { | |
| "up" { | |
| $notify.Icon = $iconOk | |
| $notify.BalloonTipText = "All systems UP" | |
| } | |
| "late" { | |
| $notify.Icon = $iconWarn | |
| $notify.BalloonTipText = "Some systems are LATE" | |
| } | |
| "down" { | |
| $notify.Icon = $iconDown | |
| $notify.BalloonTipText = "One or more systems DOWN" | |
| } | |
| } | |
| $notify.ShowBalloonTip(5000) | |
| $lastNotifiedState = $currentState | |
| $pendingState = "" | |
| $firstDetectedTime = $null | |
| } | |
| } | |
| } | |
| Start-Sleep $pollSeconds | |
| } | |
| # Scheduled task run powershell in sta mode (Action=Start a program) | |
| # Program/Script: powershell.exe | |
| # Arguments: -STA -WindowStyle Hidden -ExecutionPolicy Bypass -File D:\dev\hc1\heathchecks-notifier.ps1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment