You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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全局属性动态设置路径

  1. 修改log4net.config:将<file>节点的值改为使用全局属性变量
<file value="${LogDirectory}/Logs/Logs.txt" />
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 23:20:19