|
1 | | -# WindowsServiceExtensions |
2 | | -Make a .NET Core Windows Service that runs `IHostedService` background services power event aware. On consumer OS Windows 10, shutting down the computer will actually hibernate the OS. Services won't get another OnStart call. |
| 1 | +# Windows Service Extensions |
| 2 | +Building a basic Windows Service that does some long-running background work is trivial, using .NET's [`UseWindowsService()`](https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.windowsservicelifetimehostbuilderextensions.usewindowsservice?view=dotnet-plat-ext-6.0) (from the Platform Extensions package `Microsoft.Extensions.Hosting.WindowsServices`) and [`Microsoft.Extensions.Hosting.BackgroundService`](https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.backgroundservice?view=dotnet-plat-ext-6.0) from `Microsoft.Extensions.Hosting.Abstractions`. |
3 | 3 |
|
4 | | -This project exists of a few classes that make building reliable Windows Services easier. The Lifetime class also include [kmcclellan's fixes](https://github.com/dotnet/runtime/issues/50019#issuecomment-678658133) that make the service throw when something fails on startup, instead of reprorting it started successfully. |
| 4 | +Running as a _Windows Service_ and _running BackgroundServices_ are two separate things though, and they are not connected in any way. A non-service console app can run background services, and so can and do web applications. Each of those are different hosting environments, with their own lifetimes. |
| 5 | + |
| 6 | +This project exists of a few classes that make building reliable Windows Services easier, to gap this disconnect. |
| 7 | + |
| 8 | +## Lifetime |
| 9 | +The following improvements are included in this library: |
| 10 | + |
| 11 | +* `OnStart()` can fail because of invalid service configuration, quit the application when that happens (by [kmcclellan](https://github.com/dotnet/runtime/issues/50019#issuecomment-678658133)). |
| 12 | +* On consumer OS Windows 10+, shutting down the computer will actually hibernate the OS. Services won't get another `OnStart()` call when the computer starts again, nor will your background services be notified. Now they will. |
| 13 | +* It also can notify your BackgroundServices about user session changes, i.e. logon, logoff and others. |
| 14 | +* When an exception occurs during your BackgroundService's lifetime, .NET Platform Extensions < 6 didn't stop the application host. Now it does, but it doesn't report an error to the Service Control Manager. With this extension, it does, as well as setting a process exit code: 13 in both cases ("invalid data"). |
5 | 15 |
|
6 | 16 | ## Installation |
7 | 17 | Through [NuGet](https://www.nuget.org/packages/CodeCaster.WindowsServiceExtensions/): |
8 | 18 |
|
9 | 19 | > Install-Package CodeCaster.WindowsServiceExtensions |
10 | 20 |
|
11 | 21 | ## Usage |
12 | | -These extensions allow your IHostedServices to respond to this power state change.: |
| 22 | +These methods from this package allow your `IHostedService`s to tell the Windows Service Control Manager about errors, and respond to Windows Service events relating to sessions (user logon/logoff) and power state (shutdown/hibernate/resume): |
| 23 | + |
| 24 | +* On your Host Builder, call `UseWindowsServiceExtensions()` instead of `UseWindowsService()`. |
| 25 | +* Instead of letting your service inherit `BackgroundService`, inherit from `CodeCaster.WindowsServiceExtensions.WindowsServiceBackgroundService`. |
| 26 | +* Implement `protected Task TryExecuteAsync(CancellationToken stoppingToken)` instead of `ExecuteAsync(CancellationToken stoppingToken)`. |
| 27 | +* Implement the method `public override bool OnPowerEvent(PowerBroadcastStatus powerStatus) { ... }` and do your thing when it's called with a certain status. |
| 28 | +* Implement the method `public override bool OnSessionChange(SessionChangeDescription changeDescription) { ... }` and do your thing when it's called with a certain status. |
| 29 | + |
| 30 | +Do note that the statuses received can vary. You get either `ResumeSuspend`, `ResumeAutomatic` or both reported to `OnPowerEvent()`, never neither, after a machine wake, reboot or boot. |
| 31 | + |
| 32 | +## Documentation |
| 33 | +For examples and more specific documentation, see https://codecasternl.github.io/WindowsServiceExtensions/. |
| 34 | + |
| 35 | +## Upgrading from v2 to v3 |
| 36 | +If you're one of the souls that use this library (who _are_ you?), you'll want to upgrade to v3.0 after upgrading your projects to .NET 6. |
| 37 | + |
| 38 | +Changes: |
| 39 | + |
| 40 | +* The DI extension method `IHostBuilder.UsePowerEventAwareWindowsService()` is now called `UseWindowsServiceExtensions()` because we do more than power events now. |
| 41 | +* The long-running hosted service base class `CodeCaster.WindowsServiceExtensions.PowerEventAwareBackgroundService` was renamed to `CodeCaster.WindowsServiceExtensions.Service.WindowsServiceBackgroundService`, because the former didn't have enough "Service" in its name. |
| 42 | +* Instead of `BackgroundService.ExecuteAsync()`, which is now sealed, override `WindowsServiceBackgroundService.TryExecuteAsync()` to do your long-running work. |
| 43 | + |
| 44 | +Extended upgrading docs: see https://codecasternl.github.io/WindowsServiceExtensions/upgrading-v2-v3. |
13 | 45 |
|
14 | | -* On your Host Builder, call `UsePowerEventAwareWindowsService()` instead of [`UseWindowsService()`](https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.windowsservicelifetimehostbuilderextensions.usewindowsservice?view=dotnet-plat-ext-3.1). |
15 | | -* Instead of letting your service inherit [`Microsoft.Extensions.Hosting.BackgroundService`](https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.backgroundservice?view=dotnet-plat-ext-5.0), inherit from `CodeCaster.WindowsServiceExtensions.PowerEventAwareBackgroundService`. |
16 | | -* Implement the method `public override bool OnPowerEvent(PowerBroadcastStatus powerStatus)` and do your thing when it's called with a certain status. |
| 46 | +# Contributing |
| 47 | +Please file an issue or PR. Even if you use this and are happy with it. |
17 | 48 |
|
18 | | -Do note that the statuses received can vary. You get either `ResumeSuspend`, `ResumeAutomatic` or both, never neither, after a machine wake, reboot or boot. |
|
0 commit comments