1

Context

I have a .NET Core 3.1 Console Application that is being run as a Windows service. It's set up using:

Host.CreateDefaultBuilder(args)
    .UseWindowsService()

And installed as a Windows service using sc.exe create.

Question

Some users want to install multiple versions of this same console application on the same machine, which works fine! However, when viewing the logs in the Event Viewer, you can't tell which Windows service each record belongs to, as they all have the same source name.

Is there a standard way to set up a source name at installation time?

Research

  • The documentation indicates that UseWindowsService will set the "application name" as the default source name. Which is always the same name.
  • This issue seems to indicate that there is no way to do it through configuration.
  • The following code would allow me to set it manually, but I'd like to follow an industry standard if one exists:
// Inside .ConfigureServices((hostContext, services) =>
services.Configure<EventLogSettings>(settings =>
{
    settings.SourceName = "My chosen name";
});
Stanislas
  • 1,893
  • 1
  • 11
  • 26

1 Answers1

1

As I know classical way to solution this problem is to configure several files appsettings.json like this:

appsettings.First.json

{
  "Logging": {
    "EventLog": {
      "LogName": "Test app",
      "SourceName": "FirstInstance"
    }
  }
}

appsettings.Second.json

    {
      "Logging": {
        "EventLog": {
          "LogName": "Test app",
          "SourceName": "SecondInstance"
        }
      }
    }

Then to set it almost as you show it in your example but to reference to appsettings.json section:

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .UseWindowsService()
            .ConfigureLogging((hostingContext, logging) =>
{
    logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
    logging.AddConsole();
    logging.AddEventLog(hostingContext.Configuration.GetSection("Logging:EventLog").Get<EventLogSettings>());
})
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<Worker>();
            });

And then you build your service with both configurations and install both instances. So, your logging records will be reсorded at the same event folder but will be differ in the value in the column "Source name".

kogonidze
  • 129
  • 1
  • 11
  • There's a few things that confuse me about your answer. Are you suggesting to deploy multiple appsettings.json files per built artifact, or modifying the single appsettings.json in the deployed artifact? If you're suggesting multiple appsettings.json, then how does your demonstrated code know which appsettings file to load? It feels as if I should ignore the `appsettings.Second.json` in your answer and only read the part about adding `LogName` and `SourceName` via `EventLogSettings`. – Stanislas Feb 12 '21 at 20:00
  • You can using environment variables. https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-5.0#environment-variables In case of web application you can change variable onto IIS. In case of windows services I don`t know, may be it can help https://stackoverflow.com/a/2728574/13898743 – kogonidze Feb 17 '21 at 12:42
  • I don't really see how environment variables help. How would I differentiate between them per installation? – Stanislas Feb 17 '21 at 22:20
  • No way to differentiate between installation but you dont need it. You create two instances of your app in one artefact. If you read about order of work CreateDefaultBuilder in article, you know that it will run with the same default configuration after building because you haven`t set any environment variable yet. – kogonidze Feb 18 '21 at 09:29
  • Then if you can use IIS, you set first env var for first service and second env var for second service. Then you restart both services and it begin to work with appropriate configuration, The advantage of this way is that you can swap environment variables (so you can change it to second in first service and to first in second) and all you need after that is only restart services, no any rebuilding. In .Net Framework the way to configure environment variables is probably simpler, you can set it in Azure before building, but you need to rebuild the project if you decide to swap variables. – kogonidze Feb 18 '21 at 09:31
  • Probably you can not host your app in IIS, so try to set vars in windows registry. Because I worked with appsettings.{environment}.json only with web apps. With windows services I worked in .NET Framework, when it was different app.config for different build configuration. But it should work. – kogonidze Feb 18 '21 at 09:35