I\'m trying to build a Windows Service in .Net Core 2.0 but I\'ve been banging my head on the wall for a full day and no progress at all. Everything seems to be using Core 1.0/1
In .NET Core 2.1 you are able to use the Host and HostBuilder to get a console applicaiton that runs as a service. If you containerize your console application you can deploy the container anywhere and it is just the same as running as a service. You are able to use the Host and HostBuilder to manage DI, Logging, Graceful shut down, etc in you console app. Have a look at:
Hosting services in .NET Core console application
An easy way to create a .NET Core Windows service is by using Peter Kottas' DotNetCore.WindowsService library.
The NuGet package is PeterKottas.DotNetCore.WindowsService. To install it using the Visual Studio Package Manager Console, just run
Install-Package PeterKottas.DotNetCore.WindowsService
There are good notes on how to get started, too.
As Microsoft released Microsoft.Windows.Compatibility, I would use it, as it seem to be best for future use.
Simple example of self installing service is here https://github.com/janantos/service_core
To host .NET Core 2.0 Web API as Windows Service. I followed this guide Host ASP.NET Core in a Windows Service. The Prerequisites part is unclear to me. After some mistakes, here is what I did: Source Code
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net461</TargetFramework>
<RuntimeIdentifier>win7-x64</RuntimeIdentifier>
<!--<TargetFramework>netcoreapp2.0</TargetFramework>-->
</PropertyGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
<ItemGroup>
<!--<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />-->
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.WindowsServices" Version="2.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.3" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.1" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="2.0.2" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.3" />
</ItemGroup>
</Project>
I'll summarise some options:
ServiceBase
. This will of course need the .NET Framework to be installed on the target machineI think @JeroenMostert's comment is a bit harsh - I can see the appeal of not being dependant on a particular .NET Framework version being available on the target machines. Plenty others obviously feel the same, as the 2 repos I linked to are rather popular.
It is now possible to write a Windows Service in .NET Core 2.0 without third-party libraries, thanks to the release of the Windows Compatibility Pack (at the time of writing, still in prerelease). As the page itself warns:
But before you start porting, you should understand what you want to accomplish with the migration. Just porting to .NET Core because it's a new .NET implementation isn't a good enough reason (unless you're a True Fan).
In particular, writing a Windows Service in .NET Core may now be possible, but you will not get cross-platform compatibility out of the box, because the assemblies for platforms other than Windows will just throw a PlatformNotSupportedException
if you attempt to use service code. Working around this is possible (using RuntimeInformation.IsOSPlatform
, for example), but that's another question altogether.
Also, third-party libraries may still offer a nicer interface with regards to installing the service: as of writing, the current version of the compatibility pack (2.0.0-preview1-26216-02
) does not support the System.Configuration.Install
namespace, so the default approach with a ServiceProcessInstaller
class and installutil
will not work. More on that later.
With all that said, let's suppose you have created a brand new Windows service (Service1
) from the project template (not strictly required since it contains nothing interesting, other than a class inheriting from ServiceBase
). All you need to do to make it build on .NET Core 2.0 is to edit and replace the .csproj
with the new format:
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp20</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.Compatibility" Version="2.0.0-*" />
</ItemGroup>
</Project>
And then delete properties\AssemblyInfo.cs
since it's no longer required and will conflict with version information in the project itself.
If you already have a service and it has dependencies, the conversion may be more complicated. See here.
Now you should be able to run dotnet publish
and get an executable. As mentioned, you can't use the ServiceProcessInstaller
class to install the service, so you'll have to manually
This can be done with some PowerShell. From an elevated prompt in the location that contains your published executable:
$messageResourceFile = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\EventLogMessages.dll"
New-EventLog -LogName Application -Source Service1 -MessageResourceFile $messageResourceFile
sc.exe create Service1 binPath= (Resolve-Path .\WindowsService1.exe)
This is not ideal in several ways: this hard-codes the path of the message resource file (we should really be determining where it is from the executable and the runtime paths in the registry), and it hard-codes the service name and executable name. You may want to give your project its own installation capabilities by doing some command-line parsing in Program.cs
, or use one of the libraries mentioned in Cocowalla's answer.