.NET 8 Worker Windows Service中Serilog文件日志无法生成问题
我基于.NET 8 Worker模板开发Windows Service,想用Serilog实现文件日志记录。控制台日志正常输出,但通过appsettings.json配置的文件日志始终找不到;改用代码硬编码指定路径后,日志文件能正常生成。以下是问题的核心原因及对应解决方法:
1. 相对路径的工作目录差异
Windows Service默认工作目录是C:\Windows\System32,而非程序安装目录。当你在appsettings.json中配置"path": "log.txt"时,Serilog会尝试在System32目录下创建日志文件,但该目录需要管理员权限才能写入,普通权限运行的服务会静默失败,导致你无法找到日志文件。
而代码配置中使用Path.Join(builder.Environment.ContentRootPath, "myApp.log"),明确指定了程序所在的内容根目录,因此能正常生成文件。
解决方法:
- 方法一:在配置中使用环境变量占位符(需确保安装
Serilog.Settings.Configuration包):
{ "Serilog": { "MinimumLevel": { "Default": "Information", "Override": { "Microsoft": "Information", "System": "Information" } }, "Using": ["Serilog.Sinks.Console", "Serilog.Sinks.File"], "WriteTo": [ { "Name": "Console" }, { "Name": "File", "Args": { "path": "%CONTENTROOTPATH%/log.txt", "rollingInterval": "Day" } } ] } }
- 方法二:在代码中手动拼接内容根目录路径:
var logPath = Path.Join(builder.Environment.ContentRootPath, builder.Configuration["Serilog:WriteTo:1:Args:path"]); var logger = new LoggerConfiguration() .ReadFrom.Configuration(builder.Configuration) .WriteTo.File(logPath, rollingInterval: RollingInterval.Day) .CreateLogger(); builder.Services.AddSerilog(logger);
2. appsettings.json未正确复制到输出目录
如果appsettings.json的「复制到输出目录」属性未设置为「始终复制」或「如果较新则复制」,发布或安装Windows Service后,目标目录中会缺少配置文件,Serilog读取不到文件输出配置,自然不会生成日志。
解决方法:
右键项目中的appsettings.json文件 → 属性 → 「复制到输出目录」选择「始终复制」。
3. 缺少Serilog配置读取的必要包
要让Serilog从appsettings.json读取配置,必须安装Serilog.Settings.Configuration NuGet包。若未安装,ReadFrom.Configuration(builder.Configuration)不会生效,Serilog只会使用默认配置(无文件输出)。
解决方法:
通过NuGet包管理器或.NET CLI安装:
dotnet add package Serilog.Settings.Configuration
4. 配置加载时机或方式问题
更新1中的代码虽读取了配置,但需确保builder.Configuration已正确加载appsettings.json。推荐使用UseSerilog扩展方法整合,能更好地与主机生命周期联动:
var builder = Host.CreateApplicationBuilder(args); Log.Logger = new LoggerConfiguration() .WriteTo.Console() .CreateBootstrapLogger(); try { builder.Host.UseSerilog((context, config) => { config.ReadFrom.Configuration(context.Configuration); // 可在此处额外配置,比如覆盖路径 var logPath = Path.Join(context.HostingEnvironment.ContentRootPath, "log.txt"); config.WriteTo.File(logPath, rollingInterval: RollingInterval.Day); }); builder.Services.AddWindowsService(ops => { ops.ServiceName = "DotNet Joke Service"; }); builder.Services.AddSingleton<JokeService>(); builder.Services.AddHostedService<WindowsBackgroundService>(); var host = builder.Build(); host.Run(); } catch (Exception ex) { Log.Fatal(ex, "启动时发生未处理异常"); } finally { Log.CloseAndFlush(); }
内容的提问来源于stack exchange,提问作者Tech with Thiru

