Restore Win7 launch safety: version-gate the Service menu, don't probe

The capability PROBE (added earlier for feature-detect) constructed a
ServiceController during window construction, which loaded System.ServiceProcess
on EVERY launch. On Win11 that's harmless, but on Win7 it meant the app was
attempting that risky load at startup, surviving only on a catch — too fragile
for a guarantee. Verified empirically: a normal launch was loading
System.ServiceProcess.ServiceController.dll again.

Fix: decide Service-menu visibility with a Windows-VERSION check
(OperatingSystem.IsWindowsVersionAtLeast(10,0)) instead of a runtime probe. A
version check touches no service type, so the service assembly is NOT referenced
at launch on any OS. On Win7/8 the menu is hidden and that assembly is never
loaded; on Win10+ it loads only later, if the user actually opens the Service
menu (already wrapped in try/catch). Feature-detecting on Win7 and keeping Win7
launch-safe are mutually exclusive (you can't test the load without doing it),
so we choose guaranteed launch safety.

- Deleted ServiceCapability (the probe) — now unused.
- Replaced its self-test with "Main window builds without loading the service
  assembly (Win7-safe)": constructing the main window must not load
  System.ServiceProcess. Verified empirically too: normal launch now loads 0
  service modules (was 1).

Gate 33/33.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ednunp
2026-07-14 20:03:17 +01:00
co-authored by Claude Opus 4.8
parent 541f66d379
commit 0567ea22c3
3 changed files with 30 additions and 63 deletions
+10 -8
View File
@@ -2182,14 +2182,16 @@ public sealed class MainForm : Form
// and the arrow keys.
menu.Items.Add(fileMenu);
menu.Items.Add(recordMenu);
// Offer the Service menu wherever the send-only service can actually run — feature-detected, not
// gated on a Windows version, so it appears on Windows 7 too if the .NET service layer loads there
// (Ed's ask: install on "Win7 or above" wherever it's supported). ServiceCapability probes safely:
// if System.ServiceProcess can't load on this OS, it catches that and the menu is simply hidden, so
// an older Windows can never be crashed by it. The startup path is already service-type-free via
// ServiceEntry, so this probe (at window construction, never at launch) is the only place that
// decides visibility.
if (ServiceCapability.IsAvailable())
// Offer the Service menu on Windows 10+ only. This is a VERSION check on purpose, not a runtime
// probe: a probe would have to construct a ServiceController to test it, which loads
// System.ServiceProcess — the exact assembly that won't load on Windows 7 — during window
// construction on EVERY launch. Deciding by version is free (it touches no service type), so on
// Windows 7/8 the menu is simply hidden and that assembly is never referenced at launch at all,
// which is what keeps the app launching there. On Windows 10+ the assembly loads only later, if the
// user actually opens the Service menu (the DropDownOpening handler, wrapped in try/catch). Feature-
// detecting on Win7 and keeping Win7 launch-safe are mutually exclusive — you can't test whether the
// assembly loads without loading it — so we choose guaranteed launch safety.
if (OperatingSystem.IsWindowsVersionAtLeast(10, 0))
menu.Items.Add(BuildServiceMenu());
menu.Items.Add(optionsMenu);
menu.Items.Add(helpMenu);