Worker Service looking for appsettings.json in System32 folder instead of local folder

8.1k Views Asked by At

I have a .Net core worker service, which I am running as a windows service. The service is using appsettings.json file for the config information. After installing the service using SC CREATE command, the service was failing.

In the event viewer I found the error it cannot find the file C:\Windows\System32\appsettings.json. My service files are placed in a different folder c:\Services\, instead of looking at that location, the service is looking for a the file in System32 folder.

The configuration registration is as below.

 var configBuilder = new ConfigurationBuilder()
                   .SetBasePath(Directory.GetCurrentDirectory())
                   .AddJsonFile("appsettings.json");
var configuration = configBuilder.Build();
            services.AddSingleton(configuration);

How can I make the service to look at the local folder?

4

There are 4 best solutions below

5
itminus On BEST ANSWER

That's because the current directory is changed to C:\Windows\System32 at runtime. You could get a relative path by Assembly.GetExecutingAssembly(). For example:

var configBuilder = new ConfigurationBuilder()
    .SetBasePath( Path.GetDirectoryName( Assembly.GetExecutingAssembly().Location))
    .AddJsonFile("appsettings.json");
var configuration = configBuilder.Build();
0
vieira42 On

I´ve successfully used the docs in Host ASP.NET Core in a Windows Service

In a nutshell, you should just add .UseWindowsService() in your configuration builder step, like in the following:

Host.CreateDefaultBuilder(args)
    .UseWindowsService()
    .ConfigureAppConfiguration((hostContext, configuration) => 
        {
            //...set your configurations here
        })
        .ConfigureServices((hostContext, services) =>
        {
            //...configure you services here
        }
0
Max Medina On

I solved it differently by setting the ContentRoot. But I'm installing the service to windows using Wix.

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.Diagnostics;
using System.IO;

namespace ConverterService
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
            string pathToContentRoot = Path.GetDirectoryName(pathToExe);

            CreateHostBuilder(args, pathToContentRoot).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args, string contentRoot) =>
            Host.CreateDefaultBuilder(args)
                .UseWindowsService()
                .UseContentRoot(contentRoot)
                .ConfigureServices((hostContext, services) =>
                {
                    ConverterConfig config = hostContext.Configuration
                    .GetSection("ConverterConfig")
                    .Get<ConverterConfig>();

                    config.RootPath = contentRoot;

                    services.AddSingleton(config);
                    services.AddHostedService<WindowsBackgroundService>();
                });
    }
}

1
Jan Bennewitz On

I found that Assembly.GetExecutingAssembly().Location (as suggested in other answers) returned an empty string when called from a .Net 8 Windows service. AppContext.BaseDirectory is what worked for me. source

The code in the question would need to change to:

var configBuilder = new ConfigurationBuilder()
    .SetBasePath(AppContext.BaseDirectory)
    .AddJsonFile("appsettings.json");