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

Log4net配置:实现重启应用仍追加日志至同一文件

解决log4net重复生成日志文件的问题

我来帮你搞定这个日志文件的问题——你当前的配置里,每次启动应用时log4net都会重新解析%date{yyyyMMdd_HHmmss}这个表达式,所以每次都会生成一个新的文件名,哪怕appendToFile设为true也没用,因为目标文件不一样嘛。

想要实现仅在首次启动(或旧文件被删/重命名时)创建带生成时间的日志文件,之后一直追加到该文件的需求,这里有两种可行方案:

方案一:启动时手动检查并确定日志文件名(完全贴合需求)

这个方法逻辑直观,能精准满足你的要求:每次启动先检查目标目录有没有符合格式的日志文件,有就追加,没有就新建带当前时间的文件。

步骤1:修改App.config配置

把原来的文件名表达式替换为log4net的全局属性占位符,这样我们可以在代码里动态设置文件名:

<appender name="FileAppender" type="log4net.Appender.FileAppender">
    <!-- 用全局属性作为文件名占位符 -->
    <file type="log4net.Util.PatternString" value="%property:LogFileName" />
    <appendToFile value="true" />
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date{dd-MMM-yyyy HH:mm:ss,fff} %level - %message%newline" />
    </layout>
</appender>

步骤2:在应用启动时设置日志文件名

在应用的入口(比如Program.cs的Main方法)里添加逻辑,检查现有文件并设置全局属性:

using System.IO;
using System.Linq;
using log4net;
using log4net.Config;

namespace YourAppNamespace
{
    class Program
    {
        static void Main(string[] args)
        {
            // 定义日志存储目录和文件名规则
            string logDirectory = @"D:\";
            string logFilePrefix = "Log_";
            string logFileExtension = ".txt";

            // 确保目录存在
            if (!Directory.Exists(logDirectory))
            {
                Directory.CreateDirectory(logDirectory);
            }

            // 查找目录下所有符合格式的日志文件
            var existingLogFiles = Directory.GetFiles(logDirectory, $"{logFilePrefix}*{logFileExtension}");
            string targetLogFile;

            if (existingLogFiles.Length > 0)
            {
                // 取最新创建的日志文件(你也可以根据需求选择其他规则,比如最早的)
                targetLogFile = existingLogFiles
                    .OrderByDescending(filePath => new FileInfo(filePath).CreationTime)
                    .First();
            }
            else
            {
                // 生成新的带当前时间的文件名
                string currentTimeStamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
                targetLogFile = Path.Combine(logDirectory, $"{logFilePrefix}{currentTimeStamp}{logFileExtension}");
            }

            // 设置log4net全局属性,供配置文件使用
            log4net.GlobalContext.Properties["LogFileName"] = targetLogFile;

            // 初始化log4net
            XmlConfigurator.Configure();

            // 测试日志
            var logger = LogManager.GetLogger(typeof(Program));
            logger.Info("应用启动成功");
        }
    }
}

这样每次启动应用时:

  • 如果目标目录有日志文件,就追加到最新的那个
  • 如果文件被删除或重命名,就自动创建带当前时间的新文件
  • 你的原有日志调用代码(比如ABC类里的logMe.Info)完全不用修改,直接生效

方案二:自定义PatternConverter缓存首次启动时间(适合固定文件名场景)

如果你希望文件名固定为应用首次启动的时间(即使旧文件被删,新创建的文件名还是首次启动的时间),可以用这种方式:

步骤1:创建自定义PatternConverter

这个转换器会在首次加载时记录当前时间,之后一直返回这个缓存值:

using log4net.Util;
using System;

namespace YourAppNamespace
{
    public class LogCreationTimeConverter : PatternConverter
    {
        private static readonly string _creationTimeStamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");

        protected override void Convert(System.IO.TextWriter writer, object state)
        {
            writer.Write(_creationTimeStamp);
        }
    }
}

步骤2:修改App.config注册转换器并使用

<log4net>
    <!-- 注册自定义转换器 -->
    <converter>
        <name>logCreationTime</name>
        <!-- 替换成你的程序集名称,比如你的项目编译后的exe/dll名字 -->
        <type>YourAppNamespace.LogCreationTimeConverter, YourAppAssembly</type>
    </converter>

    <appender name="FileAppender" type="log4net.Appender.FileAppender">
        <!-- 使用自定义转换器生成文件名 -->
        <file type="log4net.Util.PatternString" value="D:\Log_%logCreationTime.txt" />
        <appendToFile value="true" />
        <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date{dd-MMM-yyyy HH:mm:ss,fff} %level - %message%newline" />
        </layout>
    </appender>

    <root>
        <level value="ALL" />
        <appender-ref ref="FileAppender" />
    </root>
</log4net>

注意:这个方案的文件名是固定的,即使旧文件被删除,重新创建的文件名还是首次启动的时间,不符合“删除后创建新的带当时时间的文件”的需求,所以更适合需要固定文件名的场景。

你的原有日志调用代码无需任何修改,配置完成后就能正常工作。

内容的提问来源于stack exchange,提问作者John Evans Solachuk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:21:16