.NET Core 3.1 Windows服务中log4net日志目录指定问题
.NET Core 3.1 Windows服务log4net日志路径修正
问题描述
将.NET Core 3.1应用作为Windows服务运行时,log4net日志默认保存到C:/Windows/System32/Logs,而非应用程序.exe所在目录。同一解决方案中的Web应用可正常将日志保存到发布文件夹,需调整配置使Windows服务的日志路径指向程序目录。
现有配置文件及代码如下:
log4net.config
<?xml version="1.0" encoding="utf-8" ?> <log4net> <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender"> <file value="Logs/Logs.txt" /> <encoding value="utf-8" /> <appendToFile value="true" /> <rollingStyle value="Date" /> <maxSizeRollBackups value="10" /> <maximumFileSize value="50MB" /> <staticLogFileName value="true" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%-5level %date [%-5.5thread] %-40.40logger - %message%newline" /> </layout> </appender> <root> <appender-ref ref="RollingFileAppender" /> <level value="INFO" /> </root> </log4net>
Startup.cs 配置代码
public IServiceProvider ConfigureServices(IServiceCollection services) { var configFilepath = Path.Combine(_env.ContentRootPath, "log4net.config"); return services.AddAbp<EMMSubscriberModule>( options => options.IocManager.IocContainer.AddFacility<LoggingFacility>( f => f.UseAbpLog4Net().WithConfig(configFilepath) ) ); }
Program.cs 代码
public static void Main(string[] args) { var host = BuildWebHost(args); if (Debugger.IsAttached || args.Contains("--debug")) { host.Run(); } else { host.RunAsService(); } } public static IWebHost BuildWebHost(string[] args) { ... return WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .UseContentRoot(AppDomain.CurrentDomain.BaseDirectory) .Build(); }
解决方案
Windows服务默认工作目录为C:/Windows/System32,log4net使用相对路径时会基于此目录生成日志文件。可通过以下方式指定日志路径为程序所在目录:
方法一:利用log4net全局属性动态设置路径
- 修改log4net.config:将
<file>节点的值改为使用全局属性变量
<file value="${LogDirectory}/Logs/Logs.txt" />
- 在Program.cs中设置全局属性:在构建Host前,将
LogDirectory属性设置为程序所在目录
using log4net; public static IWebHost BuildWebHost(string[] args) { // 获取程序所在目录 var exeDirectory = AppDomain.CurrentDomain.BaseDirectory; // 设置log4net全局属性 log4net.GlobalContext.Properties["LogDirectory"] = exeDirectory; ... return WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .UseContentRoot(exeDirectory) .Build(); }
方法二:通过代码动态修改log4net Appender路径
在Startup.cs的ConfigureServices方法中,读取log4net配置后手动修改Appender的文件路径:
using log4net; using log4net.Appender; using log4net.Repository.Hierarchy; using System.Reflection; public IServiceProvider ConfigureServices(IServiceCollection services) { var configFilepath = Path.Combine(_env.ContentRootPath, "log4net.config"); // 加载log4net配置 var logRepository = LogManager.GetRepository(Assembly.GetEntryAssembly()); XmlConfigurator.Configure(logRepository, new FileInfo(configFilepath)); // 修改RollingFileAppender的路径 if (logRepository is Hierarchy hierarchy) { var appender = hierarchy.GetAppenders().OfType<RollingFileAppender>().FirstOrDefault(); if (appender != null) { appender.File = Path.Combine(_env.ContentRootPath, "Logs/Logs.txt"); appender.ActivateOptions(); // 使配置生效 } } return services.AddAbp<EMMSubscriberModule>( options => options.IocManager.IocContainer.AddFacility<LoggingFacility>( f => f.UseAbpLog4Net().WithConfig(configFilepath) ) ); }
额外注意事项
- 确保Windows服务运行账户拥有程序所在目录的写入权限,否则日志可能因权限不足无法写入,甚至回退到System32目录。
- 若使用方法一,需确保log4net在读取配置前已设置好全局属性,否则变量无法被解析。
内容的提问来源于stack exchange,提问作者Ask
相关产品推荐
相关产品推荐

