Подтвердить что ты не робот

Не удается заставить 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);

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

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

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

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

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

4b9b3361

Ответ 1

По дизайну Log4Net есть

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

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

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

FROM FAQ - 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)
    {


    }
}

Ответ 2

Обратите внимание, что когда процесс запускается как служба 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")));

Ответ 3

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

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>

Код С#

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

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

Ответ 4

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

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

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

Офир

Ответ 5

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

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

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

Ответ 6

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

  • Убедитесь, что у вас есть свойства файла log4net.config Скопировать на вывод, установленный для копирования Всегда, проверьте, проверяя файл в каталоге 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

Ответ 7

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

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

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

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

Ответ 8

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

Ответ 9

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

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

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

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

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

  • попробуйте другую конфигурацию. просто получите образец конфигурации для где-то в Интернете.

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

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

Ответ 10

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

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

Ответ 11

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

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

где {{folder_path}} - это путь к вашему log4net.config

Ответ 12

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

Ответ 13

В продолжение комментария от Янтин Чен в вышеуказанной теме - С помощью приведенного ниже кода вы можете узнать, что все сообщения конфигурации регистрируются 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());

    }