No log file created when calling UseWindowsService

Viewed 1030

I followed the Serilog instructions to add a very basic log file to my application.

I am able to reproduce it doing the following:

  • Created a new ASP.NET Core Web Api with Visual Studio with the default parameters: .NET 5, no authentication, configured for HTTPS, enabling OpenAPI support
  • Installed the Serilog.AspNetCore package
  • Installed the Microsoft.Extensions.Hosting.WindowsServices package (so I could call the UseWindowsService() extension method)
  • Edited my Program.cs class as follow:
public class Program
{
    public static void Main(string[] args)
    {
        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Information()
            .WriteTo.File("logs.txt", rollingInterval: RollingInterval.Day)
            .CreateLogger();

        try
        {
            Log.Information("Starting Web Host");
            CreateHostBuilder(args).Build().Run();
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "Host terminated unexpectedly");
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseWindowsService()
            .UseSerilog()
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}
  • Removed the Logging section from the app.settings:
{
  "AllowedHosts": "*"
}

So far, when I run the web api from Visual Studio or the windows explorer, everything works great: the file logs.txt is created as expected and the web api is alive.

But then, when I create a windows service to run the app:

sc.exe create TestService binPath="path\to\WebApplication1.exe"

Despite the web api running well, there is no log file created.

Here is some of the things I tried:

  • Changed the user running the service with my own account => no change
  • Removed the call to UseWindowsService() => the web api does not start
  • Used another provider (NLog) => same behavior: no log file created
  • Switched the calls between UseWindowsService() and UseSerilog() => no change
  • Called UseWindowsService() and UseSerilog() (in both order) after ConfigureWebHostDefaults() => no change

What did I do wrong? May be the whole run as a windows service part is not the best way to run my web api as a service?

1 Answers

The first rule of Serilog troubleshooting is to enable SelfLog and see what error messages are being thrown by the Serilog sink.


Most likely it's a permission issue (i.e. the account doesn't have permission to write to the folder you're attempting to write to).

.WriteTo.File("logs.txt", ...) writes to the current working directory, and in the case of Windows Services usually means %WINDIR%\System32 - which I'm sure it's not the place you want to store your logs anyway.

Thus you need to be more explicit about the path you want to write your logs to, and make sure it points to a folder the account used for running the service will have write access to.

A common pattern is to define the path in a configuration file (e.g. appSettings.json) and retrieve that.

If you're looking to write to the same folder where your Windows Service binaries are, a reliable way nowadays is to use Process.GetCurrentProcess().MainModule?.FileName (1). E.g:

var startupPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule?.FileName);
var logFilePath = Path.Combine(startupPath, "logs.txt");

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .WriteTo.File(logFilePath, rollingInterval: RollingInterval.Day)
    .CreateLogger();

(1) In a future version of .NET, you'll be able to use Environment.ProcessPath or Environment.ApplicationDirectory

Related