it-swarm.dev

nie można uzyskać log4net działającego z usługą Windows .net

Mam usługę Windows z kodem app.config i 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>

Dodałem to również w AssemblyInfo.cs:

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

W jednej z moich klas mam:

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

i

_log.Info(content);

Podałem wszystkim użytkownikom pełne uprawnienia do mojego folderu Dzienniki.

Mój folder bin (z którego usługa jest uruchomiona) ma zarówno mój kod app.config, jak i log4net.config.

Ale nie wygenerowano żadnego pliku rejestrowania. Jakie ustawienia przegapiłem?

Zaktualizowano 4 marca 2014 r.

Jeśli używasz osobnego pliku konfiguracyjnego, jak ja (log4net.config), pamiętaj, aby ustawić ustawienie Copy to output directory na Copy always w Eksploratorze rozwiązań

31
Null Reference

Według projektu Log4Net jest 

fail-stop, rozumiemy, że log4net nie wyśle ​​nieoczekiwanych wyjątków w czasie wykonywania potencjalnie powoduje awarię aplikacji

Dlatego bardzo trudno jest ustalić, co powoduje problem.

Jak włączyć wewnętrzne debugowanie log4net?

FROM FAQ - http://logging.Apache.org/log4net/release/faq.html

  • Wewnętrzne debugowanie można również włączyć, ustawiając wartość w pliku konfiguracyjnym aplikacji (Nie plik konfiguracyjny log4net, , Chyba że dane konfiguracyjne log4net są osadzone w pliku konfiguracyjnym aplikacji ). Ustawienie aplikacji log4net.Internal.Debug musi być Ustawione na wartość true. Na przykład:
<?xml version="1.0" encoding="utf-8" ?> 
<configuration>
            <appSettings>
                <add key="log4net.Internal.Debug" value="true"/>
            </appSettings> 
</configuration>

To ustawienie jest odczytywane natychmiast po uruchomieniu i spowoduje, że wszystkie wewnętrzne komunikaty debugowania będą emitowane.

  • . Aby programowo włączyć wewnętrzny debug log4net, musisz ustawić właściwość log4net.Util.LogLog.InternalDebugging na true . Oczywiście, im szybciej to zostanie ustawione, tym więcej debugowania zostanie wyprodukowane.

Oto tutaj niestandardowa klasa, którą stworzyłem dla log4Net - ponieważ plik konfiguracyjny było bardzo mylące. Stworzyłem tę klasę pomocniczą

  • możesz zainicjować tyle aplikacji, ile potrzebujesz w aplikacjach więc jeśli jeden dll wywoła inną bibliotekę dll, może zainicjować dodatki i oba dodatki będą działać.
  • również możesz zamknąć aplikację i (jak w przypadku programu do dodawania plików) następnie wyślij go jako e-mail
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); 

Ustaw tę właściwość na 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)
    {


    }
}
22
dekdev

Należy pamiętać, że gdy proces jest uruchamiany jako usługa Windows, Environment.CurrentDirectory będzie mieć postać „C: Windows 32”

Jeśli więc umieścisz plik konfiguracyjny log4net (log4net.config) obok pliku * .exe, możesz użyć następującego kodu do skonfigurowania log4net.

var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
XmlConfigurator.Configure(new FileInfo(Path.Combine(assemblyFolder, "log4net.config")));
16
YantingChen

Oto konfiguracja, która działa dla mnie.

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>

Kod C #

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

Mam tę konfigurację w projekcie biblioteki klasy C # i wszystkie inne projekty używają tego odwołania do projektu, aby rejestrować wyjątki.

10
Deeptechtons

Po sprawdzeniu i ponownym sprawdzeniu ... :-)

Wszystko, czego potrzebujesz, to wywołanie XmlConfigurator.Configure(); przed utworzeniem rejestratora (tylko raz).

Cieszę się, że ci pomogłem,

Ofir

9
Ofir

Jeśli utworzysz inny plik konfiguracyjny i umieścisz w nim rzeczy związane z log4net, będziesz musiał użyć [Assembly: log4net.Config.XmlConfigurator(ConfigFile = @"...\log4net.config", Watch = true)] inside AssemblyInfo.cs zamiast tylko

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

W przeciwnym razie musisz umieścić <log4net> ... </log4net> część konfiguracji w swoim App.config

5
Alpay

Kiedy mówisz „Wszyscy użytkownicy” mają pełne uprawnienia do katalogu dziennika, czy obejmuje to konta usług?

Sprawdź, czy LocalService, NetworkService, LocalSystem itp. Mają uprawnienia (w zależności od kontekstu usługi).

Ponadto, zakładając, że masz wiązkę do uruchomienia usługi jako aplikacji, czy rejestrowanie działa, gdy działasz jako użytkownik?

Jeśli nie działa poprawnie jako aplikacja, masz problem z konfiguracją log4net (którą inne odpowiedzi próbowały rozwiązać).

3
l33tmike

Przepraszam, jeśli niektóre z nich wydają się oczywiste, ale to właśnie sprawdzę:

  • Upewnij się, że masz właściwości pliku log4net.config Kopiuj do wyjścia ustaw na Kopiuj zawsze, sprawdź, czy plik znajduje się w katalogu bin

  • Zwróć także uwagę na dokumenty log4net związane z właściwościami AssemblyInfo.cs:

Używanie atrybutów może być jaśniejszą metodą definiowania miejsca, z którego zostanie załadowana konfiguracja aplikacji. Jednak warto zauważając, że atrybuty są czysto pasywne. Są to tylko informacje . Dlatego jeśli używasz atrybutów konfiguracyjnych, musisz wywołać log4net aby umożliwić mu odczytanie atrybutów. Proste połączenie z LogManager.GetLogger spowoduje atrybuty wywołującego zestawu do czytania i przetwarzania. Dlatego konieczne jest wykonanie rejestrowanie połączenia jak najwcześniej podczas uruchamiania aplikacji i na pewno przed załadowaniem jakichkolwiek zewnętrznych zespołów i wywołany .

  • Aby rozwiązać problem, możesz spróbować przełączyć się z właściwości poziomu złożenia na jawne wywołanie konfiguracji

    XmlConfigurator.Configure ();

    powinien być wystarczający.

  • Zawsze robię log4net.config pełnym plikiem konfiguracyjnym, zaczynając od

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

Nie powinieneś potrzebować niczego w app.config powiązanym z log4net, o ile twój plik konfiguracyjny to log4net.config

3
SteveM

Czy mógłbyś przesłać Ci aplikację, aby sama mogła ją debugować? 

kilka polecam sprawdzić:

  1. zamień wszystkie „” w ścieżce do pliku na „

  2. umieść całą konfigurację log4net osadzoną w pliku konfiguracyjnym aplikacji.

  3. włącz debugowanie log4net ( zobacz tutaj )

  4. spróbuj innej konfiguracji. po prostu pobierz przykładową konfigurację gdzieś w Internecie.

  5. dla pewności, dałbym maksymalne uprawnienia wszystkim użytkownikom do twojego katalogu logowania

  6. spróbuj odinstalować usługę i zainstalować ją ponownie.

1
Uri Abramson

log4net działa pod uprawnieniami aktywnego użytkownika. Upewnij się, że aktywny użytkownik ma uprawnienia do tworzenia/modyfikowania/usuwania określonego pliku tekstowego.

1
user2373845

jeśli masz osobny plik dla log4net.config. Czy ustawiłeś następującą właściwość:

Kopiuj do katalogu wyjściowego = Kopiuj zawsze

0
shawtza

W kontynuacji komentarza Yanting Chen w powyższym wątku - poniższy kod pozwala sprawdzić, jakie loginet rejestrują wszystkie komunikaty konfiguracyjne podczas uruchamiania aplikacji w programie Windows Scheduler. Może to pomóc komuś uzyskać wgląd w log4net, szczególnie gdy działa on w ramach usług lub harmonogramu, gdzie nie widać ekranu poleceń.

  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());

    }
0
Phantom

Usługa Windows z logowaniem systemowym nie ma dostępu do wszystkich obecnych katalogów .. Spróbuj więc zalogować się w „C: Użytkownicy Public AppData” .

0

Widziałem, że twój kod ma niewielki problem w AssemblyInfo.cs.

zamień swój kod na: [Zgromadzenie: log4net.Config.XmlConfigurator (ConfigFile = "{{folder_path}} log4net.config")]

gdzie {{ścieżka_folderu}} jest ścieżką twojego log4net.config

0
Essie