ASP.Net Core 2.1作为Windows服务运行时无法找到appsettings.json
解决ASP.NET Core 2.1服务找不到appsettings.json的问题
这个问题的核心很明确:你的Configuration静态属性在Main方法执行之前就完成初始化了,这时候你还没来得及设置服务的当前目录,所以Directory.GetCurrentDirectory()返回的是Windows服务默认的C:\WINDOWS\system32,自然找不到发布目录里的配置文件。
问题分析
看你的代码,public static IConfiguration Configuration { get; } = new ConfigurationBuilder()...这行是静态初始化逻辑,CLR会在Main方法运行前就执行这段代码。而你设置当前目录的逻辑是在Main里的if (isService)块里,这时候配置已经加载失败了,根本没机会修正路径。
解决方案
有两种简单的修复方式,选一种就行:
方案1:把配置初始化移到Main方法内
把静态的Configuration改为延迟初始化,等设置好当前目录之后再构建:
public class Program { public static IConfiguration Configuration { get; private set; } public static void Main(string[] args) { // 先处理服务的当前目录设置 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); } } // 现在再初始化配置 Configuration = 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(); ConfigureSerilog(); // 后续的host构建逻辑不变... } // 其他方法保持不变 }
方案2:直接用程序所在目录作为配置基路径,不依赖当前目录
这种方法更稳妥,不管当前目录是什么,都直接指向程序的发布目录:
public class Program { public static IConfiguration Configuration { get; } = new ConfigurationBuilder() // 替换Directory.GetCurrentDirectory()为程序所在目录 .SetBasePath(AppContext.BaseDirectory) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true) .AddUserSecrets<Startup>() .Build(); // 后续Main方法逻辑可以保留,也可以去掉设置当前目录的代码(因为已经不依赖它了) }
验证步骤
- 任选一种方案修改代码,重新发布应用到目标目录
- 用
sc delete casapi删除旧服务,再重新创建并启动 - 查看Windows应用日志,应该不会再出现找不到配置文件的错误
另外,你用--console启动正常,是因为控制台模式下当前目录就是发布目录,所以Directory.GetCurrentDirectory()能拿到正确路径,而服务模式下默认目录是system32,这就是两种模式的差异所在。
内容的提问来源于stack exchange,提问作者whiskytangofoxtrot
相关产品推荐
相关产品推荐

