не удалось заставить log4net работать со службой .net windows

У меня есть служба Windows с app.config и log4net.config.

app.config:

  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>
  <log4net configSource="log4net.config" />

log4net.config:

<log4net>
  <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
    <param name="File" value="D:\Projects\Integration\Interface Module\bin\Logs\MyFirstLogger.log"/>
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    <appendToFile value="true" />
    <rollingStyle value="Size" />
    <maxSizeRollBackups value="2" />
    <maximumFileSize value="1MB" />
    <staticLogFileName value="true" />
    <layout type="log4net.Layout.PatternLayout">
      <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
    </layout>
  </appender>

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

Я также добавил это в AssemblyInfo.cs:

[assembly: log4net.Config.XmlConfigurator(Watch = true)]

И на одном из моих занятий у меня есть:

private readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

а также

_log.Info(content);

Я предоставил всем пользователям полные права доступа к моей папке журналов.

Моя папка bin (из которой работает служба) содержит как мои app.config, так и log4net.config.

Но файл журнала не был сгенерирован. Какие настройки я пропустил?

Обновлено 4 марта 2014 г.

Если вы используете отдельный файл конфигурации, как я (log4net.config), не забудьте установить для параметра Copy to output directory значение Copy always в обозревателе решений.


person Null Reference    schedule 06.05.2013    source источник
comment
Это работает в приложении IIS? Вам нужно будет предоставить IIS_IUSRS полные разрешения для каталога журнала, если это так.   -  person PhilChuang    schedule 06.05.2013
comment
Он размещен как служба Windows   -  person Null Reference    schedule 06.05.2013
comment
Вы упомянули о предоставлении пользователю разрешения на вашу папку журнала, но действительно ли ваша служба работает от имени пользователя (в отличие от чего-то вроде LocalService)?   -  person sgmoore    schedule 09.05.2013
comment
Атрибут [assembly: log4net.Config.XmlConfigurator(Watch = true)] и вызов LogManager.GetLogger находятся в одной сборке?   -  person YK1    schedule 15.05.2013


Ответы (14)


По дизайну Log4Net

fail-stop, мы имеем в виду, что log4net не будет генерировать неожиданные исключения во время выполнения, что может привести к сбою вашего приложения.

Поэтому очень сложно понять, что вызывает проблему.

Как включить внутреннюю отладку log4net?

ИЗ часто задаваемых вопросов — http://logging.apache.org/log4net/release/faq.html

  • Внутреннюю отладку также можно включить, установив значение в файле конфигурации приложения (не в файле конфигурации log4net, если только данные конфигурации log4net не встроены в файл конфигурации приложения). Для параметра приложения log4net.Internal.Debug должно быть установлено значение true. Например:
<?xml version="1.0" encoding="utf-8" ?> 
<configuration>
            <appSettings>
                <add key="log4net.Internal.Debug" value="true"/>
            </appSettings> 
</configuration>

Этот параметр считывается сразу при запуске и вызывает отправку всех внутренних отладочных сообщений.

  • . Чтобы программно включить внутреннюю отладку log4net, необходимо установить для свойства log4net.Util.LogLog.InternalDebugging значение true. Очевидно, что чем раньше это будет установлено, тем больше отладки будет произведено.

Итак, вот пользовательский класс, который я создал для log4Net - поскольку файл конфигурации был очень запутанным, я создал этот вспомогательный класс.

  • вы можете инициировать столько приложений, сколько вам нужно, в приложениях, поэтому, если одна dll вызывает другую dll, обе могут инициировать приложения, и оба приложения будут работать.
  • также вы можете закрыть приложение и (как в случае приложения файла), а затем отправить его по электронной почте
Log4NetFileHelper log = new Log4NetFileHelper();
        log.Init(); //Initialize
        log.AddConsoleLogging(); //Add Console Logging
        log.AddFileLogging(Path.Combine(AssemblyDirectory, "BatchConsole.log")); 
        log.AddFileLogging(Path.Combine(AssemblyDirectory,"BatchConsole_error.log"),log4net.Core.Level.Error); 

Установите для этого свойства значение True log4net.Util.LogLog.InternalDebugging=true;

public class Log4NetFileHelper
{
    private string  DEFAULT_LOG_FILENAME=string.Format("application_log_{0}.log",DateTime.Now.ToString("yyyyMMMdd_hhmm"));
    Logger root;
    public Log4NetFileHelper()
    {

    }

    public virtual void Init()
    {
        root = ((Hierarchy)LogManager.GetRepository()).Root;
        //root.AddAppender(GetConsoleAppender());
        //root.AddAppender(GetFileAppender(sFileName));
        root.Repository.Configured = true;
    }

    #region Public Helper Methods
    #region Console Logging
    public virtual void AddConsoleLogging()
    {
        ConsoleAppender C = GetConsoleAppender();
        AddConsoleLogging(C);
    }

    public virtual void AddConsoleLogging(ConsoleAppender C)
    {
        root.AddAppender(C);
    }
    #endregion

    #region File Logging
    public virtual FileAppender AddFileLogging()
    {
        return AddFileLogging(DEFAULT_LOG_FILENAME);
    }

    public virtual FileAppender AddFileLogging(string sFileFullPath)
    {
        return AddFileLogging(sFileFullPath, log4net.Core.Level.All);
    }

    public virtual FileAppender AddFileLogging(string sFileFullPath, log4net.Core.Level threshold)
    {
        return AddFileLogging(sFileFullPath, threshold,true);  
    }

    public virtual FileAppender AddFileLogging(string sFileFullPath, log4net.Core.Level threshold, bool bAppendfile)
    {
        FileAppender appender = GetFileAppender(sFileFullPath, threshold , bAppendfile);
        root.AddAppender(appender);
        return appender;
    }

    public virtual SmtpAppender AddSMTPLogging(string smtpHost, string From, string To, string CC, string subject, log4net.Core.Level threshhold)
    {
        SmtpAppender appender = GetSMTPAppender(smtpHost, From, To, CC, subject, threshhold);
         root.AddAppender(appender);
         return appender;
    }

    #endregion


    public log4net.Appender.IAppender GetLogAppender(string AppenderName)
    {
        AppenderCollection ac = ((log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root.Appenders;

        foreach(log4net.Appender.IAppender appender in ac){
            if (appender.Name == AppenderName)
            {
                return appender;
            }
        }

        return null;
    }

    public void CloseAppender(string AppenderName)
    {
        log4net.Appender.IAppender appender = GetLogAppender(AppenderName);
        CloseAppender(appender);
    }

    private void CloseAppender(log4net.Appender.IAppender appender)
    {
        appender.Close();
    }

    #endregion

    #region Private Methods

    private SmtpAppender GetSMTPAppender(string smtpHost, string From, string To, string CC, string subject, log4net.Core.Level threshhold)
    {
        SmtpAppender lAppender = new SmtpAppender();
        lAppender.Cc = CC;
        lAppender.To = To;
        lAppender.From = From;
        lAppender.SmtpHost = smtpHost;
        lAppender.Subject = subject;
        lAppender.BufferSize = 512;
        lAppender.Lossy = false;
        lAppender.Layout = new
        log4net.Layout.PatternLayout("%date{dd-MM-yyyy HH:mm:ss,fff} %5level [%2thread] %message (%logger{1}:%line)%n");
        lAppender.Threshold = threshhold;
        lAppender.ActivateOptions();
        return lAppender;
    }

    private ConsoleAppender GetConsoleAppender()
    {
        ConsoleAppender lAppender = new ConsoleAppender();
        lAppender.Name = "Console";
        lAppender.Layout = new 
        log4net.Layout.PatternLayout(" %message %n");
        lAppender.Threshold = log4net.Core.Level.All;
        lAppender.ActivateOptions();
        return lAppender;
    } 
    /// <summary>
    /// DETAILED Logging 
    /// log4net.Layout.PatternLayout("%date{dd-MM-yyyy HH:mm:ss,fff} %5level [%2thread] %message (%logger{1}:%line)%n");
    ///  
    /// </summary>
    /// <param name="sFileName"></param>
    /// <param name="threshhold"></param>
    /// <returns></returns>
    private FileAppender GetFileAppender(string sFileName , log4net.Core.Level threshhold ,bool bFileAppend)
    {
        FileAppender lAppender = new FileAppender();
        lAppender.Name = sFileName;
        lAppender.AppendToFile = bFileAppend;
        lAppender.File = sFileName;
        lAppender.Layout = new 
        log4net.Layout.PatternLayout("%date{dd-MM-yyyy HH:mm:ss,fff} %5level [%2thread] %message (%logger{1}:%line)%n");
        lAppender.Threshold = threshhold;
        lAppender.ActivateOptions();
        return lAppender;
    }

    //private FileAppender GetFileAppender(string sFileName)
    //{
    //    return GetFileAppender(sFileName, log4net.Core.Level.All,true);
    //}

    #endregion

    private void  ConfigureLog(string sFileName)
    {


    }
}
person dekdev    schedule 13.05.2013

Обратите внимание, что когда процесс запускается как служба Windows, Environment.CurrentDirectory будет "C:\Windows\system32"

Поэтому, если вы поместите файл конфигурации log4net (log4net.config) рядом с *.exe, вы можете использовать следующий код для настройки log4net.

var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
XmlConfigurator.Configure(new FileInfo(Path.Combine(assemblyFolder, "log4net.config")));
person YantingChen    schedule 20.04.2016
comment
Это было для меня. Также обратите внимание, что по той же причине вы, вероятно, не хотите использовать относительные пути в именах файлов журналов, поскольку они окажутся в папке windows\system32, если разрешения вообще разрешают запись. - person N8allan; 06.07.2017
comment
Хороший ответ. Работал и для меня. - person andrew pate; 16.09.2019

Вот конфиг, который работает для меня.

AssemblyInfo.cs

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

Log4net.Config

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
    <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender,log4net">
            <param name="File" value="C:\TEMP\Logs.txt"/>
            <lockingModel type="log4net.Appender.FileAppender+MinimalLock,log4net" />
            <appendToFile value="true" />
            <rollingStyle value="Size" />
            <maxSizeRollBackups value="2" />
            <maximumFileSize value="1MB" />
            <staticLogFileName value="true" />
        <layout type="log4net.Layout.PatternLayout,log4net">
            <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
        </layout>
    </appender>
    <root>
         <level value="ALL" />
         <appender-ref ref="LogFileAppender" />
    </root>
</log4net>

Код C#

private static readonly log4net.ILog Logger = log4net.LogManager.GetLogger(typeof(class_name));

У меня есть эта настройка в проекте библиотеки классов С#, и все остальные проекты используют эту ссылку на проект для регистрации исключений.

person Deeptechtons    schedule 16.05.2013
comment
в моем случае проблема оказалась с FileAppender. Я заменил его RollingFileAppender, и он работал нормально. Раньше ничего не помогало. - person realnero; 09.12.2013
comment
Только изменить GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); и работает отлично спасибо человек! - person Hernaldo Gonzalez; 04.05.2016

После проверки и перепроверки... :-)

Все, что вам нужно, это вызвать XmlConfigurator.Configure(); перед созданием регистратора (только один раз).

Рад помочь вам,

Офир

person Ofir    schedule 09.05.2013
comment
Я сделал это в моем AssemblyInfo.cs [сборка: log4net.Config.XmlConfigurator(Watch = true)] - person Null Reference; 09.05.2013
comment
Я думаю, вам нужно либо вызвать XmlConfigurator.Configure(), либо изменить свой AssemblyInfo.cs, чтобы использовать [assembly: log4net.Config.XmlConfigurator(Watch = true, ConfigFile=log4net.config)] - person sgmoore; 09.05.2013
comment
У меня не работает в файле AssemblyInfo.cs. Пожалуйста, вызовите 'XmlConfigurator.Configure();' перед «GetLogger». Дайте мне знать, если это все еще не работает. - person Ofir; 12.05.2013

Если вы создадите другой файл конфигурации и поместите в него вещи, связанные с log4net, вам нужно будет использовать [assembly: log4net.Config.XmlConfigurator(ConfigFile = @"...\log4net.config", Watch = true)] внутри AssemblyInfo.cs, а не просто

[assembly: log4net.Config.XmlConfigurator(Watch = true)]

В противном случае вам придется поместить <log4net> ... </log4net> часть конфигурации в файл App.config.

person Alpay    schedule 09.05.2013
comment
ConfigFile = @...\log4net.config ‹- это должен быть полный каталог? Или я просто поставил именно ...\log4net.config - person Null Reference; 11.05.2013
comment
Это должен быть полный путь к файлу log4net.config. если он находится, например, в вашем C:\temp, вы должны ввести C:\temp\log4net.config я не уверен, что он принимает относительные пути, стоит попробовать - person Alpay; 11.05.2013
comment
Эта статья ясно объясняет использование. Я надеюсь, что это помогает - person Alpay; 15.05.2013

Извините, если некоторые из них кажутся очевидными, но я бы проверил следующее:

  • Убедитесь, что в свойствах файла log4net.config Copy to Output установлено значение Copy Always, проверьте наличие файла в каталоге bin.

  • Также обратите внимание на документы log4net, относящиеся к свойствам AssemblyInfo.cs:

Использование атрибутов может быть более четким методом определения того, откуда будет загружаться конфигурация приложения. Однако стоит отметить, что атрибуты являются чисто пассивными. Они только информация. Поэтому, если вы используете атрибуты конфигурации, вы должны вызвать log4net, чтобы позволить ему прочитать атрибуты. Простой вызов LogManager.GetLogger вызовет чтение и обработку атрибутов вызывающей сборки. Поэтому крайне важно сделать вызов ведения журнала как можно раньше во время запуска приложения и, конечно же, до того, как будут загружены и вызваны какие-либо внешние сборки.

  • Для устранения неполадок вы можете попробовать переключиться со свойства уровня сборки на явный вызов конфигурации.

    XmlConfigurator.Configure();

    должно быть достаточно.

  • Я всегда делаю log4net.config полным конфигурационным файлом, начиная с

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <configSections>
        <section name="log4net" 
           type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
      </configSections>
      <log4net>
    ...
      </log4net>
    </configuration>
    

Вам не нужно ничего в app.config, связанном с log4net, если ваш файл конфигурации log4net.config

person SteveM    schedule 09.05.2013

Когда вы говорите, что «Все пользователи» имеют полные права доступа к каталогу журналов, включают ли они учетные записи служб?

Убедитесь, что у LocalService, NetworkService, LocalSystem и т. д. есть разрешения (в зависимости от того, в каком контексте запущена служба).

Кроме того, если у вас есть система для запуска службы в качестве приложения, работает ли ведение журнала при работе от имени пользователя?

Если оно не работает нормально как приложение, у вас проблема с конфигурацией log4net (которую пытались решить другие ответы).

person l33tmike    schedule 14.05.2013

log4net работает под привилегиями активного пользователя. Убедитесь, что у активного пользователя есть права на создание/изменение/удаление указанного текстового файла.

person user2373845    schedule 12.05.2013

Не могли бы вы загрузить свое приложение, чтобы я мог отлаживать его самостоятельно?

несколько, которые я рекомендую проверить:

  1. замените все "\" в пути к файлу на "\"

  2. поместите всю конфигурацию log4net, встроенную в файл конфигурации приложения.

  3. включить отладку log4net (см. здесь)

  4. попробуйте другую конфигурацию. просто возьмите образец конфигурации где-нибудь в Интернете.

  5. просто чтобы быть уверенным, я бы дал максимальные разрешения для всех пользователей в вашем каталоге журналов

  6. попробуй удалить службу и переустановить.

person Uri Abramson    schedule 15.05.2013

В продолжение комментария Янтина Чена в приведенной выше ветке. С помощью приведенного ниже кода вы можете узнать, какие все сообщения конфигурации регистрируются log4net при запуске приложения в планировщике Windows. Это может помочь кому-то получить представление о log4net, особенно при работе в службах или планировщике, где вы не видите командный экран.

  private static void InstanceLogger()
    {
        if (logger == null)
            logger = LogManager.GetLogger(typeof(Utility));

        // Code to troubleshoot Log4Net issues through Event log viewer
        StringBuilder sb = new StringBuilder();

        foreach (log4net.Util.LogLog m in logger.Logger.Repository.ConfigurationMessages)
        {
            sb.AppendLine(m.Message);
        }

        throw new Exception("String messages: " + sb.ToString());

    }
person Phantom    schedule 04.09.2019

если у вас есть отдельный файл для log4net.config. Вы установили следующее свойство:

Копировать в выходной каталог = Копировать всегда

person shawtza    schedule 19.08.2015

Я видел, что в вашем коде есть небольшая проблема в AssemblyInfo.cs.

замените свой код на: [сборка: log4net.Config.XmlConfigurator(ConfigFile = "{{folder_path}}\log4net.config")]

где {{folder_path}} – путь к файлу log4net.config.

person Essie    schedule 02.07.2018

Служба Windows с системным входом не имеет доступа ко всем присутствующим каталогам. Так что попробуйте войти в "C:\Users\Public\AppData". Это сработало для меня

person Vaibhav Revankar    schedule 07.11.2018

Запуск Dbgview.exe из Microsoft SysinternalsSuite от имени администратора --> Capture Global Win32 - -> запустите свою службу, показал мне, что мой log4net.config просто не находится в том же каталоге, что и исполняемый файл службы Windows. Щелкните левой кнопкой мыши log4net.config в VS и в «Свойствах» -> «Дополнительно» -> установите «Копировать в выходной каталог»: «Копировать, если новее». Таким образом, сборка включит файл в корзину, поскольку это необходимо для запуска службы.

person xinthose    schedule 28.04.2020