Search code examples
.net.net-corewindows-servicesservice-workerbackgroundworker

How to install multiple services under same project in .NET Core Hosted Services


Currently I'm in the process of converting an existing .NET Framework Windows service to .NET Core 3+ Worker service.

In the existing windows service project, there are multiple services registered inside the same project. Meaning Services are added to the list and run using the service base as below

ServicesList sc = new List<ServiceBase>();
sc.Add(new Worker1());
sc.Add(new Worker2());
ServiceBase.Run(sc.ToArray());

In order to install these services, we leverage the installutil from .NET Framework folder as below.

installutil.exe "<ProjectPackagePath>.exe"

This would install both the services with the names service1 and service2

How can i achieve the same for a .NET Core hosted Service containing multiple services under the same project (self-contained publish or not)?

I'm aware of the PowerShell New-Service command or the old fashioned sc.exe command to install services, but these are only used to install individual services with a ServiceName attribute.

Thanks in advance.


Solution

  • In order to help others trying to find a solution for this problem, I'm answering my own question.

    After a lot of research, I could not find a way in which, i could just use one command to install multiple services in a project

    Below is the approach that I finally went for


    1. Publish

    My AppSettings.json contains configuration that defines - if a service should be registered. Based on this config the services are then conditionally registered in Program.cs -> ConfigureServices method.

    I also wanted my service to be self-contained and for it to be single file publish. Additionally, to install different services based on config I had to exclude the AppSettings.json from the single file exe. To do that I added the ExcludeFromSingleFile config in .csproj as below

    <Content Update="appsettings.json">
       <CopyToPublishDirectory>Always</CopyToPublishDirectory>
       <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
    </Content>
    

    In order to publish I used the below command

    dotnet publish -r win-x64 -c Release --self-contained=true /p:PublishSingleFile=true /p:DebugType=None -o ${PublishPath}
    

    2. Install

    Since the Appsettings.json was published as a separate file I just created copies of the same publish folder and changed the config file to enable registration of different services.

    Finally to install each of them, I used the below commands.

    sc.exe create MyServiceName binpath="{FullExePath-WithExeName}" displayname="{MyServiceDisplayName}" start=auto
    sc.exe description MyServiceName "MyServiceDescription"
    sc.exe start MyServiceName
    

    Hope this helps.