Service: menu before Options + start-after-audio dependency

Local checkpoint - NOT for public release.

- Service menu now sits before Options in the menu bar (File / Record / Service /
  Options / Help), per Ed.
- The service is registered with depend= Audiosrv/AudioEndpointBuilder, so Windows
  starts it the instant the audio services are ready at boot (before login) - the
  earliest point WASAPI capture can find any audio. It CANNOT start before the audio
  services (there'd be no endpoints to capture, and no sound exists before audio is up),
  so this is the earliest useful start. DoInstall now uses the single BuildCreateArgs
  source of truth.

Gate 25/25.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ednunp
2026-07-12 20:34:34 +01:00
co-authored by Claude Opus 4.8
parent 004e01306b
commit 91b3f0c1c1
2 changed files with 10 additions and 8 deletions
+1 -1
View File
@@ -2170,8 +2170,8 @@ public sealed class MainForm : Form
// and the arrow keys.
menu.Items.Add(fileMenu);
menu.Items.Add(recordMenu);
menu.Items.Add(optionsMenu);
menu.Items.Add(BuildServiceMenu());
menu.Items.Add(optionsMenu);
menu.Items.Add(helpMenu);
return menu;
}
+9 -7
View File
@@ -94,11 +94,7 @@ public static class ServiceControl
var exe = Environment.ProcessPath;
if (string.IsNullOrEmpty(exe)) return 2;
// sc.exe's key= value syntax needs a space after '='. The binPath value is the quoted exe path
// plus the run verb, and that whole value is itself quoted — hence the escaped inner quotes.
var createArgs =
$"create {ServiceName} binPath= \"\\\"{exe}\\\" {RunVerb}\" start= auto DisplayName= \"{DisplayName}\"";
var rc = RunSc(createArgs);
var rc = RunSc(BuildCreateArgs(exe));
if (rc != 0) return rc;
// Best-effort description; failure here doesn't fail the install.
RunSc($"description {ServiceName} \"{Description}\"");
@@ -164,7 +160,13 @@ public static class ServiceControl
}
/// <summary>Builds the exact sc.exe "create" argument string for a given exe path. Pure and
/// side-effect-free so a self-test can verify the fiddly quoting without touching the SCM.</summary>
/// side-effect-free so a self-test can verify the fiddly quoting without touching the SCM.
///
/// <para><c>depend= Audiosrv/AudioEndpointBuilder</c> makes the service start as EARLY as it usefully
/// can: the Windows Audio and Audio Endpoint Builder services must be running for WASAPI capture to
/// find any audio at all, so Windows launches RemSound the instant they're ready (at boot, before
/// login) rather than at some arbitrary later point. Starting it BEFORE the audio services isn't
/// possible — there'd be no endpoints to capture — and there's no sound to miss before audio is up.</para></summary>
internal static string BuildCreateArgs(string exePath) =>
$"create {ServiceName} binPath= \"\\\"{exePath}\\\" {RunVerb}\" start= auto DisplayName= \"{DisplayName}\"";
$"create {ServiceName} binPath= \"\\\"{exePath}\\\" {RunVerb}\" start= auto depend= Audiosrv/AudioEndpointBuilder DisplayName= \"{DisplayName}\"";
}