feat(service): add ServiceCommands skeleton with platform/admin gates
This commit is contained in:
99
src/ClaudeMailbox/Cli/ServiceCommands.cs
Normal file
99
src/ClaudeMailbox/Cli/ServiceCommands.cs
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
using System.Security.Principal;
|
||||||
|
|
||||||
|
namespace ClaudeMailbox.Cli;
|
||||||
|
|
||||||
|
public static class ServiceCommands
|
||||||
|
{
|
||||||
|
public const string ServiceName = "ClaudeMailbox";
|
||||||
|
|
||||||
|
public static Task<int> RunAsync(string[] args)
|
||||||
|
{
|
||||||
|
if (!OperatingSystem.IsWindows())
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine("Service commands are Windows-only.");
|
||||||
|
return Task.FromResult(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
var verb = args[0];
|
||||||
|
return verb switch
|
||||||
|
{
|
||||||
|
"install-service" => Task.FromResult(InstallService(args)),
|
||||||
|
"uninstall-service" => Task.FromResult(UninstallService(args)),
|
||||||
|
"start" => Task.FromResult(RunSc("start", ServiceName)),
|
||||||
|
"stop" => Task.FromResult(RunSc("stop", ServiceName)),
|
||||||
|
"status" => Task.FromResult(Status()),
|
||||||
|
_ => Task.FromResult(PrintError($"Unknown service command: {verb}")),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
|
private static bool IsAdministrator()
|
||||||
|
{
|
||||||
|
using var identity = WindowsIdentity.GetCurrent();
|
||||||
|
return new WindowsPrincipal(identity).IsInRole(WindowsBuiltInRole.Administrator);
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
|
private static int RequireAdmin()
|
||||||
|
{
|
||||||
|
if (IsAdministrator()) return 0;
|
||||||
|
Console.Error.WriteLine("This command requires Administrator privileges.");
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
|
private static int InstallService(string[] args)
|
||||||
|
{
|
||||||
|
var admin = RequireAdmin();
|
||||||
|
if (admin != 0) return admin;
|
||||||
|
|
||||||
|
Console.Error.WriteLine("install-service: not yet implemented.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
|
private static int UninstallService(string[] args)
|
||||||
|
{
|
||||||
|
var admin = RequireAdmin();
|
||||||
|
if (admin != 0) return admin;
|
||||||
|
|
||||||
|
Console.Error.WriteLine("uninstall-service: not yet implemented.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
|
private static int Status()
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine("status: not yet implemented.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
|
internal static int RunSc(params string[] scArgs)
|
||||||
|
{
|
||||||
|
var psi = new ProcessStartInfo("sc.exe")
|
||||||
|
{
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
UseShellExecute = false,
|
||||||
|
};
|
||||||
|
foreach (var a in scArgs) psi.ArgumentList.Add(a);
|
||||||
|
|
||||||
|
using var proc = Process.Start(psi)!;
|
||||||
|
var stdout = proc.StandardOutput.ReadToEnd();
|
||||||
|
var stderr = proc.StandardError.ReadToEnd();
|
||||||
|
proc.WaitForExit();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(stdout)) Console.Write(stdout);
|
||||||
|
if (!string.IsNullOrWhiteSpace(stderr)) Console.Error.Write(stderr);
|
||||||
|
return proc.ExitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int PrintError(string msg)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine(msg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user