DrainCtl

Someone disabled new connections
at 2 AM. You'll know who.

DrainCtl watches the RDS signals that matter: drain changes, sessions, performance, service health, and unusual event volume. Investigate from one secure dashboard, act on durable history, and keep the whole farm in view.

irm https://lissconsulting.github.io/LISSTech.DrainCtl/install.ps1 | iex
<1s
Detection time
365d
Default audit retention
12
Trigger types
3
Webhook + ntfy + Email
Kerberos auth
Running in production

PowerShell scripts don't call you at 2 AM.

Every RDSH admin has been there: something's wrong, users are calling, and you're RDP-ing into servers one at a time to find out who put what into drain mode and when.
The old way

PowerShell scripts

You've got a script. It polls every 5 minutes. Maybe it emails you. But it doesn't know who changed it, it can't attribute events to a user account, and the last thing you need is another fragile cron job to maintain.

DrainCtl uses kernel-level registry notifications — zero polling delay, built-in attribution via Windows Security Events.
The old way

Manual checking

Log into each server. Run chglogon /query. Check 8 hosts. Repeat. You're always the last to know — and there's no record of how long the server was drained or who was responsible.

One dashboard for your entire farm. Instant detection. SQLite-backed audit trail with timestamps, durations, and who did it.
The old way

Generic monitoring

PRTG, Zabbix, and your RMM don't understand RDSH drain semantics. They'll alert on everything or nothing, and you'll spend more time tuning thresholds than managing your farm.

DrainCtl speaks RDSH natively — it knows a 5-minute maintenance drain from a forgotten overnight drain, and tells you exactly who to call.

Complete visibility. Deliberate control.

Detect drain changes, follow sessions and performance, and investigate event anomalies across the farm. The dashboard turns retained telemetry and live status into operator-ready decisions.
⚡
Instant Detection
The moment someone runs chglogon /drain, the service knows. No polling delay — Windows notifies DrainCtl directly through the kernel.
👤
Who Changed It
DrainCtl tells you the exact user account that enabled drain mode. Not just that it changed — who did it, and when.
📈
Performance That Reads Clearly
CPU, memory, disk I/O, input delay, and optional RemoteFX come from Windows PDH. P50 and P95 use valid samples; zero FPS or quality means inactive, while missing values remain gaps.
🌐
Farm Dashboard
Live status, session capacity, durable charts, events, and server controls for the whole RDSH farm — secured with Kerberos SSO or credential login.
📊
Session Tracking
Active and disconnected sessions on every server. Capacity threshold alerts before your farm runs out of slots.
🔔
Smart Alerts
13 trigger types across drain mode, sessions, CPU, memory, input delay, and event spikes. Webhook, ntfy, and email (SMTP) with per-target intervals.
🎯
EventSpike Anomaly Detection
Steady, Chill, and Vigilant presets enable a detector that learns each channel for seven durable days while still detecting. Steady begins at 10 / 1e-4 with a 60-minute cooldown; use Channel=Minutes when one channel needs a precise override. Retrying or failed channels never mature its baseline.
📋
SQLite Audit Trail
Every state change logged with timestamps, durations, and attribution. CLI, PowerShell, or dashboard.
💾
Tiered SQLite Telemetry
Raw samples roll up to 5-minute and hourly tiers with per-tier retention. Per-host and fleet-wide queries — same store powers every chart.
📈
Fleet & Host Charts
P50 and P95 use valid samples: lower-is-better zero values are retained, while zero FPS or quality is inactive and unavailable metrics chart as gaps.
⚙️
Dashboard-Authoritative Config
Configure Alerts & Performance, Event Spikes, Notifications, Servers, and System once. Operator-safe EventSpike settings propagate to connected agents; each agent keeps its baseline path local.
🛡️
Resilient by Design
Windows restarts the service after its first or second failure. Protected local diagnostics retain service state, failure actions, WER settings, crash events, and dump inventory for troubleshooting.

Choose a dashboard host. Bring the farm online.

Install the dashboard in dashboard-only mode, then let session hosts discover it through DNS SRV — no per-machine dashboard URL.
01

Install the dashboard

Use the MSI wizard or your deployment system. Dashboard-only mode runs the listener, authentication, SQLite, and retention without local drain monitoring, performance or EventSpike collection, registration/reporting, notifications, or updater activity.

INSTALL_MODE=dashboard DASHBOARD_ONLY=1
02

Add one DNS SRV record

Point internal DNS at the dashboard host. Session-host agents discover it themselves and connect securely.

_drainctl._tcp.contoso.com → your-dashboard-host:49470
03

Operate from one place.

Connected hosts register and report. Set fleet-safe alerts, performance thresholds, notification targets, and EventSpike controls in the dashboard; agents receive the authoritative configuration on their normal fetch cadence.

Built for production RDSH farms.

Meanwhile, in the server room…
🔍

Zero-Touch Discovery

One DNS SRV record. Every agent finds the dashboard on its own. No scripts, no per-machine config, no manual URLs.

_drainctl._tcp.contoso.com
The lock clicks shut…
🔒

HTTPS
Everywhere

Auto TLS on first start. Self-signed cert, or bring your own. Certificate pinning. HSTS. Private key locked to SYSTEM.

At the notification desk…
📧

Email + Webhook + ntfy

SMTP email with HTML templates and natural-language subjects. Webhook and ntfy.sh too. Manage all targets from the dashboard with per-target triggers.

The counters are watching…
📈

Performance Monitoring

CPU, memory, input delay, disk I/O, and optional RemoteFX — collected via PDH on the configured sample interval. Threshold alerts fire before users complain.

The cmdlets assemble…
⚡

12 Cmdlets

Add-, Get-, Remove-RDSHDrainNotificationTarget. Full multi-target control from PowerShell.

The installer arrives…
📦

MSI with Superpowers

Interactive wizard or silent deploy. INSTALL_MODE=dashboard, DASHBOARD_URL=..., ENABLE_PERF=1 — configure machine-owned settings from the command line. In-place upgrades preserve settings and operational history without reopening configuration dialogs.

The latest stable release keeps your farm recoverable.

Get self-healing service recovery, restart-safe host visibility, protected local crash evidence, and telemetry that preserves uncertainty—without sacrificing the in-place upgrade path.

Self-healing service

Recover from the failures Windows can recover.

The Service Control Manager restarts DrainCtl five seconds after its first and second failures, then stops retrying. The failure count resets after one day so repeated faults remain visible.

Restart-safe host visibility

Know when a host goes offline—and when it returns.

SQLite-backed report epochs survive restarts. The dashboard emits one additive offline event after three missed heartbeats and one recovery event when reporting resumes, while keeping server-update compatibility.

Protected crash evidence

Keep local evidence without copying sensitive dumps.

WER retains up to three DrainCtl mini dumps in a permanent SYSTEM/Administrators-only ProgramData folder. Hourly diagnostics record protected metadata; DRAINCTL_INCLUDE_CRASH_DUMPS=1 hashes and gzips only the newest protected dump and never auto-uploads it.

Safe upgrades

Keep the operational history you built.

In-place upgrades preserve configuration, telemetry, host-freshness state, removed-server tombstones, the Force Update outbox, and EventSpike baselines and warm-up state.

One dashboard for your entire RDSH farm.

Watch health and retained history, investigate events, and make fleet changes without losing context. Dashboard-only mode is purpose-built for the dashboard host; connected session-host agents do the local monitoring and reporting.

Overview turns live signals and durable SQLite history into fleet trends. Servers gives operators persistent multi-select, per-server Mute/Notify, Force Update, durable removal, and restoration from Config → Servers. Events keeps investigation close to the telemetry. Config organizes fleet settings into Alerts & Performance, Event Spikes, Notifications, Servers, and System.

🔌

Dashboard-only when the host should stay focused

Run the dashboard listener, authentication, SQLite, and retention without enabling local drain monitoring, performance/EventSpike collection, registration/reporting, notifications, or the updater.

🔒

Secure by Default

Auto TLS, Kerberos SSO or credential login, certificate pinning, HSTS. Session-based auth with 8-hour timeout.

📈

Live Monitoring, Durable History

Server-Sent Events deliver live changes, including one offline and recovery signal per outage. LOAD, Health Indicators, Sessions, and optional RemoteFX charts query retained SQLite telemetry.

⚙️

Configure and Control in the UI

Manage alerts, performance, Event Spikes, notifications, Servers, and System settings in named tabs. Operator-safe EventSpike fields propagate to agents; baseline_path stays local-only.

How it detects changes in real time

Four detection mechanisms feed a single service — no agents to install, no polling gaps, no missed changes.

Registry Watch

Fires the instant drain mode changes. No polling — the OS notifies the service directly.

~0ms

Event Log Audit

Security Event 4657 tells you who made the change. Attribution you can't get from registry monitoring alone.

Who did it

Performance Counters

CPU, memory, input delay, disk queue, TCP retransmits, and optional RemoteFX metrics. Configurable sustain windows filter transient spikes.

CPU + Mem + Delay

Notifications

Webhook, ntfy, and email with per-target triggers and repeat intervals. DPAPI-encrypted secrets at rest.

3 channels

CLI, PowerShell, or both.

Every interface returns the same data. Pick the one that fits your workflow.
# Check drain mode status (instant via service pipe)
PS> drainctl check
2026-04-02T20:08:56-04:00 [INF] source=service
2026-04-02T20:08:56-04:00 [INF] host=MDS-LDC1-RDS5
2026-04-02T20:08:56-04:00 [INF] drain_mode=ALLOW_ALL_CONNECTIONS value=0
2026-04-02T20:08:56-04:00 [INF] state_since=2026-04-02T18:30:00-04:00 state_duration=1h38m56s
2026-04-02T20:08:56-04:00 [INF] grace_period=1h0m0s
2026-04-02T20:08:56-04:00 [OK ] status=Healthy connections_allowed=true exit=0

# When drain mode is active beyond grace period:
2026-04-02T22:15:00-04:00 [ERR] status=Alert connections_allowed=false exit=1
# Exit code 1 triggers your RMM monitoring threshold
# Rich status object
PS> Get-RDSHDrainMode

Timestamp            : 4/2/2026 8:08:56 PM
Host                 : MDS-LDC1-RDS5
DrainMode            : ALLOW_ALL_CONNECTIONS
StateSince           : 4/2/2026 6:30:00 PM
StateDurationSeconds : 5936
Status               : Healthy
ConnectionsAllowed   : True
Message              : All connections allowed.
ExitCode             : 0

# Boolean check for scripts and alerts
PS> if (Test-RDSHDrainMode) { "OK" } else { "ALERT" }
OK

# One-liner for monitoring scripts
PS> (Get-RDSHDrainMode).Status
Healthy
# Machine-readable output for automation
PS> drainctl check --format json
{
  "version": "26.119.10",
  "host": "MDS-LDC1-RDS5",
  "drain_mode": "ALLOW_ALL_CONNECTIONS",
  "drain_mode_value": 0,
  "state_since": "2026-04-02T18:30:00-04:00",
  "state_duration_seconds": 5936.42,
  "grace_period_seconds": 3600,
  "status": "Healthy",
  "connections_allowed": true,
  "sessions": {
    "active_sessions": 12,
    "disconnected_sessions": 3,
    "total_sessions": 15,
    "max_sessions": 25,
    "utilization_pct": 60
  },
  "message": "All connections allowed.",
  "exit_code": 0
}
# View recent state transitions with attribution
PS> Get-RDSHDrainHistory -ChangesOnly -Limit 5

Timestamp              DrainMode                             Changed  ChangedBy         Exit
---------              ---------                             -------  ---------         ----
4/2/2026 10:14:04 PM   ALLOW_RECONNECTIONS_PREVENT_NEW..     YES      MDS\lissadmin     0
4/2/2026 10:13:32 PM   ALLOW_ALL_CONNECTIONS                 YES      MDS\lissadmin     0
4/2/2026 10:10:00 PM   ALLOW_RECONNECTIONS_PREVENT_NEW..     YES      MDS\lissadmin     0
4/2/2026  8:30:00 PM   ALLOW_ALL_CONNECTIONS                 YES      MDS\svcaccount    0
4/2/2026  6:15:00 PM   ALLOW_RECONNECTIONS_PREVENT_NEW..     YES      MDS\jdoe          0

# Filter in pipeline
PS> Get-RDSHDrainHistory | Where-Object Changed | Select Timestamp, ChangedBy

Install for the role each machine has.

Use a monitoring agent on session hosts, dashboard-only on the central dashboard host, or install the PowerShell module for scripts and checks. Full guide →
Fleet deploy

Silent MSI

Deploy the same signed MSI through RMM, SCCM, Intune, or GPO. INSTALL_MODE=dashboard enables the dashboard role; add DASHBOARD_ONLY=1 when the coordinator must not monitor or report itself.

msiexec /i LISSTech.DrainCtl.msi /qn INSTALL_MODE=dashboard DASHBOARD_ONLY=1
Module only

PowerShell Gallery

Just the cmdlets — no service, no CLI. Good for quick checks and scripts. The stable module installs directly from PowerShell Gallery.

Install-Module LISSTech.DrainCtl
“We monitor 14 session hosts across 3 client sites. Before DrainCtl, we'd find out someone drained a server when users started calling. Now we know before they do.”
Built by people who manage RDSH farms every day.

LISS Technologies is a NYC-based managed services provider — in business since 1984. We manage Windows infrastructure, RDSH farms, and enterprise environments for our clients.

DrainCtl exists because we needed it. No tool on the market gave us instant drain detection with proper attribution, a farm-wide dashboard, and alerts that understood RDSH semantics — so we built one. It's been running in production at client sites since before this page existed.

We open-source the tools we'd want to use ourselves. If your team manages session hosts, you're the kind of shop we work with.

Track record

NYC-based MSP since 1984. Four decades of enterprise Windows infrastructure management.

Dogfooded first

Every tool we release is running in production at a client site before it ships publicly. DrainCtl monitors live RDSH farms daily.

Open source, no strings

Apache 2.0. Fork it, deploy it, modify it. We release tools we'd want to exist — not lead-generation demos.