Asp.net-Core-2.0

.net 核心託管為 Windows 服務 - 如何使用配置文件?

  • September 13, 2018

我有一個希望作為 Windows 服務執行的 .Net Core 2 WebAPI。預設情況下,服務在http://localhost:5000. 當我在本地執行它時,我正在使用一個hosting.json文件在那裡設置 IP 和埠,但由於某種原因,當我嘗試使用配置文件時服務不會啟動。

這是我的程式碼:

public static void Main(string[] args)
{
   var config = new ConfigurationBuilder()
       .SetBasePath(Directory.GetCurrentDirectory())
       .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
       .AddJsonFile("hosting.json", optional: false, reloadOnChange: true)
       .AddCommandLine(args)
       .Build();

   if (Debugger.IsAttached || args.Contains("--console"))
       BuildWebHost(config, args).Run();
   else
       BuildServiceWebHost(config, args).RunAsService();
}

public static IWebHost BuildWebHost(IConfigurationRoot config, string[] args)
{
   return WebHost.CreateDefaultBuilder(args)
       .UseConfiguration(config)
       .UseStartup<Startup>()
       .Build();
}

public static IWebHost BuildServiceWebHost(IConfigurationRoot config, string[] args)
{
   var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
   var pathToContentRoot = Path.GetDirectoryName(pathToExe);

   var webHostArgs = args.Where(arg => arg != "--console").ToArray();

   return WebHost.CreateDefaultBuilder(webHostArgs)
       .UseConfiguration(config)
       .UseContentRoot(pathToContentRoot)
       .UseStartup<Startup>()
       .Build();
}

它在 Debug 上執行(例如,不是作為服務),但是當我將它設置為 Windows 服務sc create MyService binPath="..."並嘗試執行它時,我收到了這個錯誤:

Windows could not start the MyService service on Local Computer.

Error 1053:
The service did not respond to the start or control request in a timely fashion.

我檢查Event Viewer並發現了這個錯誤: Exception Info: System.IO.FileNotFoundException: The configuration file 'appsettings.json' was not found and is not optional. The physical path is 'C:\WINDOWS\system32\appsettings.json'.

如何將配置文件的路徑設置為與作為.exe服務執行時的路徑相同?

我設法通過以下方式解決了這個問題:

using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;

namespace WebAPI
{
   public class Program
   {
       public static void Main(string[] args)
       {
           if (Debugger.IsAttached || args.Contains("--console"))
               BuildWebHost(args).Run();
           else
           {
               var webHost = BuildServiceWebHost(args);

               var webHostService = new CustomWebHostService(webHost);
               ServiceBase.Run(webHostService);
           }
       }

       public static IWebHost BuildWebHost(string[] args)
       {
           var config = new ConfigurationBuilder()
               .SetBasePath(Directory.GetCurrentDirectory())
               .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
               .AddJsonFile("hosting.json", optional: false, reloadOnChange: true)
               .AddCommandLine(args)
               .Build();

           return WebHost.CreateDefaultBuilder(args)
               .UseConfiguration(config)
               .UseStartup<Startup>()
               .Build();
       }

       public static IWebHost BuildServiceWebHost(string[] args)
       {
           var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
           var pathToContentRoot = Path.GetDirectoryName(pathToExe);

           var webHostArgs = args.Where(arg => arg != "--console").ToArray();

           JObject hosting = JsonConvert.DeserializeObject<JObject>(File.ReadAllText($"{pathToContentRoot}/hosting.json"));
           return WebHost.CreateDefaultBuilder(webHostArgs)
               .UseUrls(hosting.Value<string>("server.urls"))
               .UseContentRoot(pathToContentRoot)
               .UseStartup<Startup>()
               .Build();
       }
   }
}

希望這可以幫助其他人在同樣的問題上苦苦掙扎。

引用自:https://stackoverflow.com/questions/51304106