feat(installer): add Stop/StartServiceStep sc.exe wrappers
This commit is contained in:
27
src/ClaudeDo.Installer/Steps/StartServiceStep.cs
Normal file
27
src/ClaudeDo.Installer/Steps/StartServiceStep.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using ClaudeDo.Installer.Core;
|
||||||
|
|
||||||
|
namespace ClaudeDo.Installer.Steps;
|
||||||
|
|
||||||
|
public sealed class StartServiceStep : IInstallStep
|
||||||
|
{
|
||||||
|
private const string ServiceName = StopServiceStep.ServiceName;
|
||||||
|
|
||||||
|
public string Name => "Start Worker Service";
|
||||||
|
|
||||||
|
public async Task<StepResult> ExecuteAsync(InstallContext ctx, IProgress<string> progress, CancellationToken ct)
|
||||||
|
{
|
||||||
|
progress.Report($"Starting {ServiceName}...");
|
||||||
|
|
||||||
|
var (exit, output) = await ProcessRunner.RunAsync("sc.exe", $"start {ServiceName}", null, progress, ct);
|
||||||
|
if (exit == 0) return StepResult.Ok();
|
||||||
|
|
||||||
|
// Exit 1056 = already running — that's fine too.
|
||||||
|
if (output.Contains("1056", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
progress.Report("Service was already running.");
|
||||||
|
return StepResult.Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
return StepResult.Fail($"sc.exe start failed with exit code {exit}");
|
||||||
|
}
|
||||||
|
}
|
||||||
48
src/ClaudeDo.Installer/Steps/StopServiceStep.cs
Normal file
48
src/ClaudeDo.Installer/Steps/StopServiceStep.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using ClaudeDo.Installer.Core;
|
||||||
|
|
||||||
|
namespace ClaudeDo.Installer.Steps;
|
||||||
|
|
||||||
|
public sealed class StopServiceStep : IInstallStep
|
||||||
|
{
|
||||||
|
public const string ServiceName = "ClaudeDoWorker";
|
||||||
|
|
||||||
|
public string Name => "Stop Worker Service";
|
||||||
|
|
||||||
|
public async Task<StepResult> ExecuteAsync(InstallContext ctx, IProgress<string> progress, CancellationToken ct)
|
||||||
|
{
|
||||||
|
progress.Report($"Stopping {ServiceName} (if running)...");
|
||||||
|
|
||||||
|
// sc.exe query -> returns non-zero if the service does not exist; that's fine.
|
||||||
|
var (queryExit, queryOutput) = await ProcessRunner.RunAsync("sc.exe", $"query {ServiceName}", null, progress, ct);
|
||||||
|
if (queryExit != 0)
|
||||||
|
{
|
||||||
|
progress.Report("Service is not registered — nothing to stop.");
|
||||||
|
return StepResult.Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queryOutput.Contains("STOPPED", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
progress.Report("Service is already stopped.");
|
||||||
|
return StepResult.Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
var (stopExit, _) = await ProcessRunner.RunAsync("sc.exe", $"stop {ServiceName}", null, progress, ct);
|
||||||
|
if (stopExit != 0)
|
||||||
|
return StepResult.Fail($"sc.exe stop failed with exit code {stopExit}");
|
||||||
|
|
||||||
|
// Poll until stopped or timeout (up to 30s).
|
||||||
|
for (var i = 0; i < 30; i++)
|
||||||
|
{
|
||||||
|
ct.ThrowIfCancellationRequested();
|
||||||
|
await Task.Delay(1000, ct);
|
||||||
|
var (e, o) = await ProcessRunner.RunAsync("sc.exe", $"query {ServiceName}", null, progress, ct);
|
||||||
|
if (e != 0 || o.Contains("STOPPED", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
progress.Report("Service stopped.");
|
||||||
|
return StepResult.Ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return StepResult.Fail("Service did not stop within 30 seconds.");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user