ASP.Net Core 2.1 application cannot find appsettings.json when ran as a Windows service

痞子三分冷 提交于 2020-04-13 17:00:07

问题


I am trying to run my ASP.Net Core 2.1 application as a service on Windows 10. My application runs fine when ran using VS2017 or if I publish to a folder and then start it from within that published folder with the --console arg. However, if I use sc create to create the service, getting a Success result, and then try to run it, I get an error in the Windows Application log stating...

System.IO.FileNotFoundException: The configuration file 'appsettings.json' was not found and is not optional. The physical path is 'C:\WINDOWS\system32\appsettings.json'.
at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load(Boolean reload)   

I have confirmed that my appsettings.json file exists in the published folder. The error message states that is is looking in the C:\WINDOWS\system32\ folder for the appsettings.json file rather than the published folder where the application .exe resides. This leads me to think the issue is with the way the current directory is being set when ran as a service, but I am having trouble identifying exactly why it is not working.

I have set up my Program.cs by following the instructions in this Microsoft document. My program.cs is shown below;

public class Program
{

    public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
        .AddUserSecrets<Startup>()
        .Build();

    public static void Main(string[] args)
    {
        ConfigureSerilog();


        // Set up to run as a service if not in Debug mode or if a command line argument is not --console
        var isService = !(Debugger.IsAttached || args.Contains("--console"));
        if (isService)
        {
            var processModule = Process.GetCurrentProcess().MainModule;
            if (processModule != null)
            {
                var pathToExe = processModule.FileName;
                var pathToContentRoot = Path.GetDirectoryName(pathToExe);
                Directory.SetCurrentDirectory(pathToContentRoot);
            }
        }

        var builder = CreateWebHostBuilder(args.Where(arg => arg != "--console").ToArray());
        var host = builder.Build();
        if (isService)
        {
            host.RunAsCustomService();
        }
        else
        {
            try
            {
                Log.Information("Starting CAS API in Program.cs");
                host.Run();
            }
            catch (Exception ex)
            {
                Log.Fatal(ex, "CAS API Host terminated unexpectedly");
            }
            finally
            {
                Log.CloseAndFlush();
            }
        }
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureLogging((hostingContext, logging) => { logging.AddEventSourceLogger(); })
            .ConfigureAppConfiguration((context, config) =>
            {
                // Configure the app here.
            })
            .UseStartup<Startup>()
            .UseSerilog()
            .UseUrls("https://localhost:60026"); //This is only used when ran as a stand-alone service. Not in VisualStudio

    private static void ConfigureSerilog()
    {
        // Set up Serilog
        var connectionString = Configuration.GetConnectionString("CasDbConnectionString");
        const string tableName = "Logs";

        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Information()
            .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
            .Filter.ByExcluding(Matching.FromSource("Microsoft.EntityFrameworkCore.Query"))
            .Enrich.FromLogContext()
            .Enrich.WithMachineName()
            .Enrich.WithThreadId()
            .Enrich.WithUtcTimeStamp()
            .Enrich.WithProperty("Application", $"{System.Reflection.Assembly.GetExecutingAssembly().GetName().Name}")
            .Enrich.FromLogContext()
            .CreateLogger();

    }

I have tried replacing the...

host.RunAsCustomeService();

with ...

host.RunAsService();

And I still had the same problem.

I am running the sc command as follows;

sc create casapi start= auto binPath= c:\deployments\casapi\casapi.exe

And I see the casapi service listed in Windows Services. But if I run the sc command...

sc start casapi 

I get the error indicated above.

If I go to the published folder in an elevated command prompt and type... casapi.exe --console The application runs as expected.

The casapi service is installed to Log On as a local system account.


回答1:


As App configuration, we need to call SetCurrentDirectory and use a path to the app's published location.

For your issue, you access Directory.GetCurrentDirectory() before calling Directory.SetCurrentDirectory(pathToContentRoot); as you call ConfigureSerilog(); first.

Try to change the order like

    // Set up to run as a service if not in Debug mode or if a command line argument is not --console
    var isService = !(Debugger.IsAttached || args.Contains("--console"));
    if (isService)
    {
        var processModule = Process.GetCurrentProcess().MainModule;
        if (processModule != null)
        {
            var pathToExe = processModule.FileName;
            var pathToContentRoot = Path.GetDirectoryName(pathToExe);
            Directory.SetCurrentDirectory(pathToContentRoot);
        }
    }
    ConfigureSerilog();



回答2:


Try this.

Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);



回答3:


If you're using Task Scheduler, you can write the directory you want into

Action Tab --> Edit --> Start in

So the program will start running from that directory.



来源:https://stackoverflow.com/questions/56956349/asp-net-core-2-1-application-cannot-find-appsettings-json-when-ran-as-a-windows

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!