Goal: I'm trying to run a .Net Core 3.1 Worker service as a windows service.
Setup: I've used the Worker service default template via Visual Studio.
To add windows service functionality to this, I installed the Microsoft.Extensions.Hosting.WindowsServices
nuget and thereafter added .UseWindowsService()
as follows:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
})
;
Thereafter, the service can be successfully started via:
sc create <WorkerSvcName> binPath=<C:/local/path/to/exe>
sc start <WorkerSvcName>
Problem:
However, I need to use further extension methods on IHostBuilder
, like for example ..UseSerilog()
. When I do so, in addition to the above setup, I always get:
[SC] StartService FAILED 1053:
The service did not respond to the start or control request in a timely fashion.
What I've tried: This persists for all the following configurations:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
X
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
})
X
.UseWindowsService()
X
as well as:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
X
.UseWindowsService()
X
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
})
X
;
where X is a custom extension method on IHostBuilder:
public static IHostBuilder UseSerilog(this IHostBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.UseSerilog((context, services, configuration) =>
{
//do stuff
configuration
.ReadFrom.Configuration(config)
.ReadFrom.Services(services)
});
Log.Information("Serilog has been configured");
return builder;
}
The alternative placements above tell me this may not have anything to do with the order of configuration in CreateHostBuilder()
.
Question: Any ideas on why I cannot use any other extension methods and continue running the windows service?
This turned out to be a glorious waste of time, since I was looking in exactly the wrong place for quite a while. But it did point out a neat way to get logs from a failing windows service.
My Serilog section in appsettings.json looked like:
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.File",
"Serilog.Sinks.Async",
"Serilog.Sinks.Elasticsearch",
"Serilog.Sinks.ApplicationInsights",
"Serilog.Sinks.NewRelic.Logs"
],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
.....
},
{
"Name": "Async",
"Args": {
"configure": [
{
"Name": "File",
..........
}
},
{
"Name": "Elasticsearch",
"Args": {
.......
}
},
{
"Name": "ApplicationInsights",
"Args": {
.......
}
},
{
"Name": "NewRelicLogs",
"Args": {
"applicationName": "<val>",
"licenseKey": "<val>" <-----------------THIS LINE WAS MISSING!!!!!!!
}
}
]
There was indeed a log about this- it just was not in the windows service console window or the console opened up via Visual Studio's IIS Express profile.
To seek logs for failing windows services, try this approach:
The resulting logs saved the day for me. Not sure why these do not appear on the console when running in either Debug or Release mode.