Search code examples
asp.net-corewindows-servicesgrpc

ASP Core .NET 6 works when I run it manually, but it fails when I install as windows service


I have an ASP Core .NET 6 application that I want to install as windows services.

I am using minimal API and this is the code:

using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Hosting.WindowsServices;
using System.IO.Compression;
using System.Security.Cryptography.X509Certificates;

using GestorOrdenadores.Service.Server.Grpc;
using Serilog;
using Microsoft.Extensions.Configuration;
using Serilog.Events;



File.AppendAllText("LogManual.txt", DateTime.Now + ": Iniciado");


Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .CreateBootstrapLogger();

Log.Information("Starting up");





try
{
    WebApplicationOptions options = new WebApplicationOptions
    {
        Args = args,
        ContentRootPath = WindowsServiceHelpers.IsWindowsService() ? AppContext.BaseDirectory : default
    };
    WebApplicationBuilder builder = WebApplication.CreateBuilder(options);


    builder.Host.UseSerilog((ctx, lc) => lc
           .WriteTo.Console()
           .ReadFrom.Configuration(ctx.Configuration));


    builder.WebHost.ConfigureKestrel((context, options) =>
    {
        string miStrCertificado = File.ReadAllText("certificados/server.crt");
        string miStrKey = File.ReadAllText("certificados/server.key");
        X509Certificate2 miCertficadoX509 = X509Certificate2.CreateFromPem(miStrCertificado, miStrKey);
        X509Certificate2 miCertificado2 = new X509Certificate2(miCertficadoX509.Export(X509ContentType.Pkcs12));

        miCertficadoX509.Dispose();


        options.ListenAnyIP(5001, listenOptions =>
        {
            listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
            listenOptions.UseHttps(miCertificado2);
        });
    });



    builder.Services.AddGrpc();

    builder.Host.UseWindowsService();



    WebApplication app = builder.Build();


    app.UseSerilogRequestLogging();

    app.MapGrpcService<GestorOrdenadoresService>();



    app.MapGet("/", () => "Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");



    await app.RunAsync();
}
catch(Exception ex)
{
    File.AppendAllText("LogManual.txt", DateTime.Now + ": EXCEPTION: " + ex.Message);
    Log.Fatal(ex, "Unhandled exception");
}
finally
{
    File.AppendAllText("LogManual.txt", DateTime.Now + ": Finally");
    Log.Information("Shut down complete");
    Log.CloseAndFlush();
}

When I debug or run the application manually, it creates the log, but when I install the service and try to run it, in the service manager of windows, when I click to start, I get the error 1067.

If I go to the event viewer of windows, I get the error with ID 7034.

And in this case no log files are created.

How the application can run when I run it manually, I guess the problem is how I try to set the service part of the code, but I don't know how could be the problem.


Solution

  • Win32 services run in %WinDir%\System32 by default (as I describe on my blog), and I'd be surprised if you could just write out a LogManual.txt in that folder. So, you're probably getting an exception, which is causing your service to fail to start.

    A lot of services find this inconvenient, and change their working directory on startup:

    Environment.CurrentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);