it-swarm.com.de

log4net funktioniert nicht mit dem .net-Windows-Dienst

Ich habe einen Windows-Dienst mit einem app.config und einem 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>

Ich habe dies auch in AssemblyInfo.cs hinzugefügt:

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

Und in einer meiner Klassen habe ich:

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

und 

_log.Info(content);

Ich habe all users volle Berechtigungen für meinen Logs-Ordner erteilt. 

Mein bin-Ordner (von dem der Dienst ausgeführt wird) enthält sowohl meinen app.config als auch log4net.config.

Es wurde jedoch keine Protokolldatei generiert. Welche Einstellungen habe ich vermisst?

Aktualisiert am 4-März-2014

Wenn Sie eine separate Konfigurationsdatei wie ich verwenden (log4net.config), denken Sie daran, die Einstellung Copy to output directory im Projektmappen-Explorer auf Copy always festzulegen

31
Null Reference

Mit Absicht ist Log4Net 

fail-stop, Wir meinen, dass log4net keine unerwarteten Ausnahmen auslöst zur Laufzeit, wodurch Ihre Anwendung möglicherweise abstürzt

Daher ist es sehr schwer herauszufinden, was das Problem verursacht.

Wie aktiviere ich das interne Debuggen von log4net?

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

  • Das interne Debugging kann auch aktiviert werden, indem Sie einen Wert in der Konfigurationsdatei der -Anwendung festlegen (nicht in der log4net-Konfigurationsdatei , Sofern die log4net-Konfigurationsdaten nicht in der Config-Datei der Anwendung eingebettet sind). Die Anwendungseinstellung "log4net.Internal.Debug" muss Auf den Wert "true" gesetzt sein. Zum Beispiel:
<?xml version="1.0" encoding="utf-8" ?> 
<configuration>
            <appSettings>
                <add key="log4net.Internal.Debug" value="true"/>
            </appSettings> 
</configuration>

Diese Einstellung wird sofort beim Start gelesen und bewirkt, dass alle internen Debugging-Meldungen ausgegeben werden.

  • . Um das interne Debuggen von log4net programmgesteuert zu aktivieren, müssen Sie .__ einstellen. die Eigenschaft log4net.Util.LogLog.InternalDebugging auf true . Je früher das gesetzt ist, desto mehr Debug wird produziert.

Hier ist eine benutzerdefinierte Klasse, die ich für log4Net erstellt habe - weil die Konfigurationsdatei Es war sehr verwirrend, dass ich diese Hilfsklasse erstellt habe

  • sie können so viele Appender initiieren, wie Sie für die Anwendungen benötigen Wenn also eine DLL eine andere DLL aufruft, können sowohl Appender als auch beide Anhänge funktionieren.
  • sie können auch den Appender schließen und (wie beim File-Appender) dann senden Sie es als 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); 

Setzen Sie diese Eigenschaft auf "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

Bitte beachten Sie, dass Environment.CurrentDirectory "C:\Windows\system32" ist, wenn der Prozess als Windows-Dienst ausgeführt wird.

Wenn Sie also die log4net-Konfigurationsdatei (log4net.config) neben Ihre * .exe stellen, können Sie log4net mit dem folgenden Code konfigurieren.

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

Hier ist die Konfiguration, die für mich funktioniert.

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 # -Code

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

Ich habe dieses Setup in C # Class Library-Projekt, und alle anderen Projekte verwenden diese Projektreferenz, um die Ausnahmen zu protokollieren.

10
Deeptechtons

Nachchecken und erneut prüfen ... :-)

Sie müssen lediglich XmlConfigurator.Configure(); aufrufen, bevor Sie den Logger erstellen (nur einmal).

Froh dir zu helfen,

Ofir

9
Ofir

Wenn Sie eine andere Konfigurationsdatei erstellen und log4net-bezogene Dinge darin ablegen, müssen Sie [Assembly: log4net.Config.XmlConfigurator(ConfigFile = @"...\log4net.config", Watch = true)] inside AssemblyInfo.cs anstelle von just verwenden

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

Andernfalls müssen Sie <log4net> ... </log4net> als Teil der Konfiguration in Ihre App.config einfügen

5
Alpay

Wenn Sie sagen, dass alle Benutzer über vollständige Berechtigungen für das Protokollverzeichnis verfügen, umfassen dies die Dienstkonten?

Überprüfen Sie, ob LocalService, NetworkService, LocalSystem usw. über Berechtigungen verfügen (abhängig davon, in welchem ​​Kontext der Dienst ausgeführt wird).

Unter der Voraussetzung, dass Sie über einen Dienst verfügen, um den Dienst als Anwendung auszuführen, funktioniert die Protokollierung, wenn Sie als Benutzer ausgeführt wird?

Wenn es als Anwendung nicht in Ordnung ist, haben Sie ein Problem mit der log4net-Konfiguration (die andere Antworten versucht haben).

3
l33tmike

Tut mir leid, wenn einige davon offensichtlich erscheinen, aber das würde ich überprüfen:

  • Vergewissern Sie sich, dass die Eigenschaften der Datei "log4net.config" in "In Ausgabe kopieren" auf "Immer kopieren" gesetzt sind, und überprüfen Sie die Datei in Ihrem bin-Verzeichnis

  • Beachten Sie auch die log4net-Dokumente, die sich auf AssemblyInfo.cs-Eigenschaften beziehen:

Die Verwendung von Attributen kann eine klarere Methode sein, um festzulegen, woher die Konfiguration der Anwendung geladen wird. Es lohnt sich jedoch Beachten Sie, dass Attribute rein passiv sind. Sie dienen nur zur Information . Wenn Sie Konfigurationsattribute verwenden, müssen Sie daher log4net .__ aufrufen. um die Attribute lesen zu können. Ein einfacher Aufruf an LogManager.GetLogger verursacht die Attribute der aufrufenden Assembly gelesen und verarbeitet werden. Daher ist es unbedingt notwendig, eine Protokollierung des Anrufs so früh wie möglich während des Anwendungsstarts und sicherlich bevor externe Baugruppen geladen wurden und aufgerufen .

  • Zur Problembehandlung können Sie versuchen, von der Eigenschaft der Assembly-Ebene zu einem expliziten Konfigurationsaufruf zu wechseln

    XmlConfigurator.Configure ();

    sollte ausreichen.

  • Ich mache log4net.config immer zu einer vollständigen Konfigurationsdatei, beginnend mit

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

Sie sollten nichts in app.config benötigen, das mit log4net zusammenhängt, solange Ihre Konfigurationsdatei log4net.config ist

3
SteveM

Könnten Sie bitte Ihre Anwendung hochladen, damit ich sie selbst debuggen kann? 

ein paar empfehle ich zu überprüfen:

  1. ersetzen Sie alle "\" in Ihrem Dateipfad in "\"

  2. fügen Sie alle log4net config in die Konfigurationsdatei der Anwendung ein.

  3. log4net-Debugging aktivieren ( siehe hier )

  4. versuchen Sie eine andere Konfiguration. Bekommen Sie einfach eine Beispielkonfiguration für irgendwo im Internet.

  5. um sicherzugehen, würde ich allen Benutzern maximale Zugriffsrechte für Ihr Protokollierungsverzeichnis geben

  6. versuchen Sie, den Dienst zu deinstallieren und neu zu installieren.

1
Uri Abramson

log4net läuft unter den Berechtigungen des aktiven Benutzers. Stellen Sie sicher, dass der aktive Benutzer die Berechtigung zum Erstellen/Ändern/Löschen der angegebenen Textdatei hat.

1
user2373845

wenn Sie eine separate Datei für log4net.config haben. Haben Sie folgende Eigenschaft festgelegt:

In das Ausgabeverzeichnis kopieren = Immer kopieren

0
shawtza

In Fortsetzung des Kommentars von Yanting Chen im obigen Thread - Mit dem folgenden Code können Sie feststellen, welche Konfigurationsnachrichten von log4net protokolliert werden, wenn die App unter Windows Scheduler ausgeführt wird. Es kann jemandem helfen, einen Einblick in log4net zu bekommen, insbesondere wenn es unter Diensten oder Schedulern ausgeführt wird, auf denen der Befehlsbildschirm nicht angezeigt wird.

  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

Der Windows-Dienst mit Systemanmeldung hat keinen Zugriff auf alle vorhandenen Verzeichnisse Melden Sie sich daher in "C:\Users\Public\AppData" . Dies hat bei mir funktioniert

0

Ich habe gesehen, dass Ihr Code in AssemblyInfo.cs ein kleines Problem hat.

ersetzen Sie Ihren Code durch: [Assembly: log4net.Config.XmlConfigurator (ConfigFile = "{Ordnerpfad}}\log4net.config"]]

dabei ist {{Ordnerpfad}} der Pfad Ihrer log4net.config

0
Essie