Search code examples
asp.net-corewindows-services

Can't start ASP.NET Core 6 app running as Windows Service


I have created a simple, stripped down project to try to get this to work: ASP.NET Core 6 WebAPI project, hosted as a Windows Service, just trying to get it up and running with the sample WeatherForecast controller. I have added NuGet package for Microsoft.Extensions.Hosting (6.0.1) and Microsoft.Extensions.Hosting.WindowsServices (6.0.0). My program.cs looks like:

 using IRDSPrototype.Configuration;
 using IRDSPrototype.Services;
 using Microsoft.Extensions.Hosting.WindowsServices;
    
 var webApplicationOptions = new WebApplicationOptions
 {
     Args = args,
     ContentRootPath = WindowsServiceHelpers.IsWindowsService() ? AppContext.BaseDirectory : default
 };
 var builder = WebApplication.CreateBuilder(webApplicationOptions);
    
 builder.Services.AddHostedService<IRDSHostingService>();
 builder.Host.UseWindowsService();
    
 builder.WebHost.UseUrls(UriServices.GetBaseUri().AbsoluteUri);
    
 // Add services to the container.
    
 builder.Services.AddControllers();
 // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
 builder.Services.AddEndpointsApiExplorer();
 builder.Services.AddSwaggerGen();
    
 var app = builder.Build();
    
 // Configure the HTTP request pipeline.
 if (app.Environment.IsDevelopment())
 {
     app.UseSwagger();
     app.UseSwaggerUI();
 }
    
 app.UseHttpsRedirection();
    
 app.UseAuthorization();
    
 app.MapControllers();
    
 await app.RunAsync();

I created a background service as well:

 public class IRDSHostingService : BackgroundService
 {
     public ILogger Logger { get; }

     public IRDSHostingService(ILoggerFactory loggerFactory)
     {
         Logger = loggerFactory.CreateLogger<IRDSHostingService>();
     }

     protected override async Task ExecuteAsync(CancellationToken stoppingToken)
     {
         Logger.LogInformation("IRDS Hosting Service is starting.");

         stoppingToken.Register(() => Logger.LogInformation("IRDS Hosting Service is stopping."));

         while (!stoppingToken.IsCancellationRequested)
         {
             await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
         }

         Logger.LogInformation("IRDS Hosting Service has stopped.");
     }
 }

I also created a service installer via Wix. When I run the installer it gets to the point of "Starting services" and fails with a message 'Verify that you have sufficient privileges to start system services'. When I check Windows Application Log, I see that error and a also see an error for:

Application: IRDSPrototype.exe CoreCLR Version: 6.0.822.36306 .NET Version: 6.0.8 Description: The process was terminated due to an unhandled exception. Exception Info: System.IO.FileNotFoundException: Could not load file or assembly 'System.ServiceProcess.ServiceController, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified. File name: 'System.ServiceProcess.ServiceController, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'

My publish directory and Wix manifest do include the System.ServiceProcess.ServiceController.dll.

I installed the service via sc.exe and the install succeeded, but starting the service gives an Error 5: Access Denied message. Unlike with the installer, though, this didn't generate any messages in the Windows log. I checked permissions on the folder containing the executable, giving full permissions to NETWORK SERVICE and LOCAL SERVICE. That didn't help. So I'm kind of stuck on what to do now. All my internet searches basically guided me to the setup I have now and it still doesn't work. So I'm at a loss. Anyone have any suggestions of what I'm missing here?

Thanks, Dennis

Edit: So I'm whittling down the problem. It turns out I needed the version of System.ServiceProcess.ServiceController.dll that was published to my 'runtimes' folder under the .Net 6.0.0 runtime. So that error no longer shows up in the Event Viewer. The only erro that shows in the Event Viewer now is:

Error 1920. Service 'IRDS Prototype' (IRDSPrototype) failed to start. Verify that you have sufficient privileges to start system services

I have it installing as a Local Service and I believe I've given Local Service full permissions on the proper folders but I will check that. Still looking for suggestions though.

Edit #2: Getting closer. The problem I had when installing through sc.exe was that my binPath was wrong. I wasn't including the exe file in the binPath. Now I can install my service through sc.exe and it starts and works properly. The service still won't start when installed via my Wix installer though. So now I'm down to a Wix issue. Anyone with experience installing Windows services via Wix?


Solution

  • OK, it turns out what I needed to do was publish as a single executable:

    enter image description here

    Notice the "Deployment Mode: Self-contained" choice and "Produce single file" checked. After publishing that way, I only had to add the executable (no other files) to my Wix manifest and the generated installer worked fine. I'm guessing I was missing a dependency somewhere that I didn't know about. But it's weird that I was able to install and start the service from the same publish directory as I was trying previously with Wix via sc.exe. Anyway, it works now. Thanks to Md Farid Uddin Kiron for redirecting me back to the official page, which I read a little more carefully this time and found the little blurb about this being recommended.