ServiceInstaller is a composable Windows Service Control Manager library with a terminal CLI. It can create, configure, query, start, stop, pause, continue, and delete services on the local computer or a remote Windows computer.
The executable you register must already implement the Windows Service hosting contract, for example with Microsoft.Extensions.Hosting.WindowsServices. Registering an ordinary console program does not turn it into a service.
dotnet add package ServiceInstaller
dotnet tool install --global ServiceInstaller.CliCreating, changing, and deleting services normally requires an elevated terminal. Remote control also requires Service Control Manager access on the target computer.
serviceinstaller create --name SampleService --display-name "Sample Service" --binary "C:\Services\Sample.exe" --description "Example worker" --start-mode automatic --start -- --service
serviceinstaller configure --name SampleService --binary "C:\Services\Sample.exe" --start-mode manual -- --service --reconfigured
serviceinstaller status --name SampleService
serviceinstaller status --name SampleService --json
serviceinstaller exists --name SampleService
serviceinstaller start --name SampleService --timeout 45 -- runtime-argument
serviceinstaller pause --name SampleService
serviceinstaller continue --name SampleService
serviceinstaller stop --name SampleService
serviceinstaller delete --name SampleService
Use --machine SERVER01 with any command to target a remote computer. install, query, resume, and uninstall are aliases for create with immediate start, status, continue, and delete respectively.
Account passwords are accepted only through standard input:
$password| serviceinstaller create --name SampleService --display-name "Sample Service"--binary "C:\Services\Sample.exe"--account ".\ServiceUser"--password-stdinThe process returns stable exit codes: 0 for success, 2 for invalid arguments, 3 for an operation failure, and 4 for an unsupported platform or access denial.
usingServiceInstaller;usingServiceInstaller.Enums;IServiceManagerservices=newWindowsServiceManager();services.Create(newServiceDefinition("SampleService","Sample Service",@"C:\Services\Sample.exe"){Arguments=["--service"],Description="Example worker",StartMode=ServiceStartMode.Automatic,Dependencies=["RpcSs"],});varrunning=services.Start("SampleService",TimeSpan.FromSeconds(30));varsnapshot=services.Query("SampleService");services.Configure("SampleService",newServiceUpdate{DisplayName="Updated Sample Service",Description="Updated description",ChangeDescription=true,StartMode=ServiceStartMode.Manual,});services.Stop("SampleService",TimeSpan.FromSeconds(30));services.Delete("SampleService",TimeSpan.FromSeconds(30));WindowsServiceManager owns native handles safely and exposes its operating-system boundary through composition, allowing service lifecycle behavior to be tested without installing real services. The original ServiceController.HandleRequest API remains available as a compatibility adapter.
The launchers bootstrap the SDK pinned by global.json when it is not installed globally, then run the Nuke build:
./build.ps1 Compile --configuration ReleaseOn Command Prompt or Unix-like shells use build.cmd or ./build.sh. Tests run on Microsoft Testing Platform with TUnit, and CI rejects production line or branch coverage below 100%.
The repository includes two GitHub Actions workflows:
BuildOnly.ymlcompiles and verifies tests and coverage for branches and pull requests.BuildDeploy.ymlperforms a manually selected semantic version bump, validates the release, packs both NuGet packages, publishes them, and creates a GitHub release.
BuildDeploy.yml expects a protected release environment and a NUGET_API_KEY secret.