Woof.ServiceInstaller
6.1.4
Prefix Reserved
See the version list below for details.
dotnet add package Woof.ServiceInstaller --version 6.1.4
NuGet\Install-Package Woof.ServiceInstaller -Version 6.1.4
<PackageReference Include="Woof.ServiceInstaller" Version="6.1.4" />
paket add Woof.ServiceInstaller --version 6.1.4
#r "nuget: Woof.ServiceInstaller, 6.1.4"
// Install Woof.ServiceInstaller as a Cake Addin #addin nuget:?package=Woof.ServiceInstaller&version=6.1.4 // Install Woof.ServiceInstaller as a Cake Tool #tool nuget:?package=Woof.ServiceInstaller&version=6.1.4
Woof.ServiceInstaller
.NET extension created by CodeDog
Distributed under MIT License. (c)2021 by CodeDog, All rights reserved.
About
Installs and runs system services on Linux and Windows.
When {command}
is your compiled service as one file native executable:
- For help use
{command} --help
. - To install:
sudo {command} --install
- To uninstall:
sudo {command} --uninstall
- To delete Windows Event Log:
{command} --delete-log
Windows
Install your executable with a Microsoft Installer first.
For protected configurations use DataProtectionScope.LocalMachine
.
The service will be registered in the location it was run with the --install
option.
On Windows, Windows Installer (MSI) is the default way to install applications, so the service installer does not copy the files elsewhere.
To check if the service is running use either Services
panel,
or type sc query {serviceName}
in cmd
.
You can also use Windows Event Log to look for entries from the service.
The service runs in LocalSystem
user context.
When the service is uninstalled with --uninstal
option it will be automatically stopped,
then unregistered. The logs will stay until deleted with --delete-log
option.
Linux
When run with sudo and --install
option, the service will be copied
to the /srv/{serviceName}
directory and the permission for the directory
will be set to user service
(the user account set in configuration).
If the system user service
does not exist it will be created.
The service will be run in service
user context.
The service can be configured to use any system user and group.
Both user and group will be created if they don't exist.
(See the ServiceMetadata XML documentation.)
Linux system services are meant to be installed from a console as root user.
To check if the service is running type service {serviceName} status
.
The logging events from the service will go to the main system log.
When the service is uninstalled with --uninstall
option
the service installed files will be deleted but the service
user will stay.
Also the Linux logs are not cleared.
Common
For service configuration options see the configuration JSON
in example,
also check the ServiceMetadata class XML documentation.
The configuration for the example service is provided with Woof.Config package.
Installing the service with the same name as an existing one will cause the current one to be automatically stopped and uninstalled first.
Naturally, the service will be uninstalled if it was installed with
Woof.ServiceInstaller
and its configuration matches.
The described feature is designed for easy software upgrades. Just install the new version, the service will be upgraded, no extra steps needed.
The installed services can be controlled (started, stopped, queried and unregistered) using the target system service controller.
The default configuration makes the service start as soon as it's installed.
The Woof.ServiceInstaller
package was made to install self-hosting WebSocket
APIs on both
Linux and Windows hosts, however additional networking setup is needed for that.
To build a WebSocket API use Woof.Net.WebSockets package.
Operation / Design
Both Windows Service and Linux systemd use the IHostedService interface.
It allows the service to be started and stopped.
The service executable is a normal executable that starts the service if run
without parameters. The process never exists unless it receives the stop signal
from the host. The services should use the CancellationToken
provided with
Start()
and Stop()
methods.
The services will restart after the host is restarted.
The command line interface
The service installer uses the Woof.CommandLine to provide a unified, POSIX type command line interface.
By default the service installer automatically binds the
--install|-i
, --uninstall|-u
and --delete-log|-d
options
to its internal handlers.
It doesn't bind the --help|-h|-?
option, it should be done in
user code, because the user code can provide its own additional
options. --query|-q
and --running|r
options are defined in the
example to illustrate how it's done.
The automatically generated help for the options can be obtained
from CommandLine.Help
property.
Similarily, command line validation errors can be obtained from
CommandLine.ValidationErrors
property after the Parse()
method was called.
Usage
Here's example Program.cs
:
using System;
using System.Threading.Tasks;
using Woof;
using Woof.Config;
using Woof.ServiceInstaller;
var config = new JsonConfig();
var commandLine = CommandLine.Default;
ServiceInstaller.Configure<TestService.TestService>(config);
if (args?.Length > 0) {
commandLine.Map<Options>();
commandLine.Delegates.Add(Options.Help, Help);
commandLine.Delegates.Add(Options.Query, QueryAsync);
commandLine.Delegates.Add(Options.Running, IsRunningAsync);
commandLine.Parse(args);
var errors = CommandLine.ValidationErrors;
if (errors is not null) Error(errors);
else await commandLine.RunDelegatesAsync();
}
else await ServiceInstaller.ServiceMetadata!.RunHostAsync<TestService.TestService>();
static void Help() => Console.WriteLine(CommandLine.Help);
static void Error(string? errorText) {
Console.WriteLine(errorText);
Console.WriteLine(CommandLine.Usage);
}
static async ValueTask IsRunningAsync()
=> Console.WriteLine((await ServiceInstaller.ServiceMetadata!.IsRunningAsync()) ? "RUNNING" : "NOT RUNNING");
static async ValueTask QueryAsync()
=> Console.WriteLine(await ServiceInstaller.ServiceMetadata!.QueryAsync());
[Usage("(sudo) {command} [--install|--uninstall|--help]")]
enum Options {
[Option("q|query", null, "Shows current service status.")]
Query,
[Option("r|running", null, "Tests if the service is running.")]
Running,
[Option("?|h|help", null, "Displays this help message.")]
Help
}
To execute code before or after installation / uninstallation simply check if the install/uninstall options are present before and/or after RunDelegatesAsync like this:
if (commandLine.HasOption(ServiceInstaller.Options.Install)) {
// code to execute
}
The installed service is started with RunHostAsync:
ServiceInstaller.ServiceMetadata!.RunHostAsync<TestService.TestService>();
If executing of some external commands is needed before or after the installation,
Shell.ExecAsync method from Woof.LinuxAdmin dependency can be used for that.
If the command executed that way fails, the method will throw an InvalidOperationException
with the error message obtained from the command output.
For more information see the included example project.
Compatibility
The package is compatible with .NET 5.0 or newer. Tested on Windows 11 and Ubuntu 20.
Disclaimer
Please report any issues on GitHub.
Woof Toolkit is a work in progress in constant development, however it's carefully maintained with production code quality.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 is compatible. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net5.0
- Microsoft.Extensions.Hosting.Systemd (>= 6.0.0)
- Microsoft.Extensions.Hosting.WindowsServices (>= 6.0.0)
- Woof.CommandLine (>= 6.0.1)
- Woof.LinuxAdmin (>= 6.1.2)
-
net6.0
- Microsoft.Extensions.Hosting.Systemd (>= 6.0.0)
- Microsoft.Extensions.Hosting.WindowsServices (>= 6.0.0)
- Woof.CommandLine (>= 6.0.1)
- Woof.LinuxAdmin (>= 6.1.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated | |
---|---|---|---|
7.0.0 | 257 | 8/6/2023 | |
6.2.0 | 541 | 2/20/2022 | |
6.1.4 | 1,409 | 11/28/2021 | |
6.1.3 | 288 | 11/27/2021 | |
6.1.2 | 1,865 | 11/26/2021 | |
6.0.5 | 2,381 | 11/25/2021 | |
6.0.4 | 291 | 11/17/2021 | |
6.0.3 | 294 | 11/15/2021 | |
6.0.2 | 408 | 11/12/2021 | |
6.0.1 | 374 | 11/11/2021 | |
5.2.7 | 420 | 11/1/2021 | |
5.2.6 | 470 | 10/30/2021 | |
5.2.5 | 434 | 10/20/2021 | |
5.2.4 | 435 | 10/20/2021 | |
5.2.3 | 382 | 10/20/2021 | |
5.2.2 | 391 | 10/15/2021 | |
5.2.1 | 376 | 10/14/2021 | |
5.2.0 | 455 | 10/14/2021 | |
5.1.1 | 429 | 10/13/2021 | |
5.1.0 | 427 | 10/12/2021 | |
5.0.3 | 404 | 8/27/2021 | |
5.0.2 | 442 | 8/27/2021 | |
5.0.1 | 427 | 8/20/2021 | |
5.0.0 | 398 | 8/19/2021 |
FIX: Dependency upgrade.