Search code examples
c#windows-services.net-core-3.1spwindowsservice

Service Starts, but The Program does not Run


We've created a new hosted service using .NET Core 3.1 and the WorkerService template.

We want to run this service as a "Windows Service".

If I run the program manually using a Powershell shell, it runs fine with no problems.

So I then added it as a windows service. To do this, I followed these steps:

  1. Added the Microsoft.Extensions.Hosting.WindowsServices package

  2. Added the following to CreateHostBuilder:

        public static IHostBuilder CreateHostBuilder(Serilog.ILogger logger, string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseWindowsService() // <-- added this line
            .ConfigureAppConfiguration(configurationBuilder =>
            {
                configurationBuilder.SetBasePath(Directory.GetCurrentDirectory())
                    .AddJsonFile("appsettings.json", optional: true);
            })
    
  3. Published it to a folder (zipped it and copied to server).

  4. Added it as a service:

PS C:\Windows\system32> sc.exe create MyService binpath= "C:\Program Files\Services\MyService.exe" 5. Opened the Services snap-in and started the service.

The snap-in shows that it has a status of "running". However, the program does not seem to actually do anything. It is not logging anything, including the most basic "Starting up" log message.

I even added a Seq sink on the off-chance that there was an IO problem preventing it from writing to a file. But nothing.

Can anyone identify what I am doing wrong?


Solution

  • As per comment on issue 36065, when a .NET Core 3.1 worker service runs as a windows service "Directory.GetCurrentDirectory() will point to %WINDIR%\system32". Therefore to get the current directory, you could use some reflection and something like:

    public static IHostBuilder CreateHostBuilder(Serilog.ILogger logger, string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseWindowsService() // <-- added this line
            .ConfigureAppConfiguration(configurationBuilder =>
            {
                configurationBuilder.SetBasePath(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location))
                    .AddJsonFile("appsettings.json", optional: true);
            });
    

    Worth noting, according to this comment, it's resolved in .NET 5.0