Log4Net在发布模式下未能写入日志 - 控制台应用程序

7
我是一位有用的助手,可以为您翻译文本。
我有一个控制台应用程序和一个类库,该类库包装了Log4Net方法。现在,在调试模式下运行应用程序时,它会写入日志,但在发布模式下构建时,它不会写入日志文件。这个问题怎么解决?以下是示例代码和配置文件。
我的开发环境是:
- Visual Studio 2013和.NET Framework 4.5
控制台应用程序:
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            log4net.GlobalContext.Properties["LogFileName"] = "TestLogin.txt";
            Logger log = new Logger(typeof(Program));
            log.Info("Logging is enabled!!");
        }
    }
}

控制台应用程序中的 App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  </configSections>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
    <log4net>
      <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
        <file type="log4net.Util.PatternString" value ="%property{LogFileName}"/> 
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%date [%thread] %level  - %message%newline%exception" />
        </layout>
      </appender>
      <root>
        <level value="ALL" />
        <appender-ref ref="RollingFileAppender" />
      </root>
    </log4net>
</configuration>

类库

using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

[assembly: log4net.Config.XmlConfigurator(Watch = true)]
namespace Logging
{
    public class Logger
    {
        private readonly ILog log = null;

        public Logger(Type type)
        {
            log = LogManager.GetLogger(type);
        }
        public void Info(object message)
        {
            log.Info(message);
        }
    }
}

我已经阅读了这篇文章,但它并没有帮助我弄清楚为什么Log4Net在发布模式下无法写入日志文件? log4net doesn't log when running a .Net 4.0 Windows application built in Release mode

我会按照这里所描述的方式启用log4net内部调试,以尝试理解发生了什么:http://logging.apache.org/log4net/release/faq.html - Joe
5个回答

7

针对这个问题,有几种解决方法。

  • 您可以在类库中的Logger构造方法上添加[MethodImpl(MethodImplOptions.NoInlining)]属性。

  • 您可以在控制台项目的AssemblyInfo.cs中添加[assembly: log4net.Config.XmlConfigurator(Watch = true)],而不是在类库项目中添加。

  • 您可以在Logger构造函数的开头添加log4net.Config.XmlConfigurator.Configure();

我认为发生这种情况的原因是,在发布模式下,您的类库被内联了,因此当log4net尝试查找属性时,它认为调用的程序集是您的exe,而不包含该属性。

附:

我假设您已经意识到,使用您的Logger类将意味着您失去了按方法名称过滤的能力,因为log4net只会看到Logger.Info方法名称。


1
在我发布这个问题之前,我尝试了最后两个选项。我尝试了第一个选项,但不幸的是它没有起作用。 - SnowWhite
非常奇怪。我尝试了所有三个选项,它们都起作用了。(如果没有它们,在发布模式下就不会发生日志记录)。你确定配置文件在你的发布文件夹中并且是正确的吗? - sgmoore
2
非常感谢您,sgmoore!我一直在Debug文件夹中检查而不是在release文件夹中检查。我的错!!!是的,它可以在释放模式下记录日志。我什么也没做。我上面列出的代码本身就起作用了,因此不需要额外的步骤来使其工作。唯一需要做的就是在发布文件夹中检查。 - SnowWhite
我想点赞,但需要15个声望点,而我只有9个 :( - SnowWhite
1
有一点需要指出。如果您通过Visual Studio运行上面的代码,则会在发布模式下创建日志,但是如果您转到发布文件夹,然后单击ConsoleApplication1.exe,则会发现没有创建日志。要解决此问题,请遵循sgmoore建议的其中一种解决方法。我遵循了第二种方法,即在Logger的构造函数中添加此行代码log4net.Config.XmlConfigurator.Configure()。现在构建解决方案,再次转到发布文件夹并单击ConsoleApplication1.exe,您将看到已创建日志。 - SnowWhite
完美的解决方案。非常好用!! 感谢@sgmoore - Sanjit Misra

1
对于已经在AssemblyInfo.cs中有[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]和在Global.asax.cs中有log4net.Config.XmlConfigurator.Configure();的MVC应用程序用户,但仍未写入日志,请确保应用程序池用户具有写入日志所在位置的权限。
为了解决这个问题,我只需在IIS服务器上创建一个日志目录(而不是在inetpub中),给它足够的权限(如果它只是一个子日志目录,你可以懒惰地选择“Everyone”、“Full Control”),并在log4net.config(或Web.config,如果你没有隔离它)中写入完整路径。
以下是我的配置文件:
<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  </configSections>
  <log4net>
    <root>
      <level value="ALL"/>
      <appender-ref ref="RollingFileAppender"/>
    </root>
    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="C:/absolute/path/to/logfile.log" />
      <appendToFile value="true" />
      <rollingStyle value="Size" />
      <maximumFileSize value="10MB"/>
      <datePattern value="yyyyMMdd'-FULL.log'" />
      <maxSizeRollBackups value="-1"/>
      <staticLogFileName value="false"/>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
      </layout>
    </appender>
  </log4net>
</configuration>

1

Properties文件夹中的AssemblyInfo.cs文件中添加代码行[assembly: log4net.Config.XmlConfigurator(Watch = true)]

enter image description here


1
你在发布模式下试过了吗?这是一段很好的代码,你应该能够快速运行而不会遇到任何麻烦。我在发布之前已经尝试过了,但它没有起作用。我又试了一次,还是不行。 - SnowWhite
这是我的 AssemblyInfo.cs 文件 [assembly: log4net.Config.XmlConfigurator(Watch = true)] [assembly: AssemblyTitle("Logging")] [assembly: AssemblyDescription("")] - SnowWhite
我有类似的代码,只不过我使用 private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 而不是创建一个 Logger 类等。 - Christian Phillips
很抱歉,我确实有一个单独的类,这是必需的要求。 - SnowWhite

1
请确保log4net.config文件已添加到您的最终发行版二进制文件中,并且与ConfigFile = "log4Net.config"中提到的路径相对应。
我曾经遇到过同样的问题,后来发现在我的发布二进制文件中简单地漏掉了这个配置文件。

0

我在我的Logging.dll和Program.exe assembly.cs中有这个。然后它可以在调试和发布模式下工作。我的程序是一个Windows服务。

[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接