Forum: PC Hard- und Software c# & log4net - Appender auf TextBox im MainForm


von Matthias S. (da_user)


Lesenswert?

Hi,

ich spiele derzeit etwas mit dem log4net. Hier und dort etwas knifflig 
einzulesen, aber wird schon.

Ich würde nun gerne in mein Hauptfenster meiner Windows-Form-Anwendung 
eine Ausgabekonsole (Mehrzeillige Textbox) unterbringen, in die ich u.A. 
Logs von log4net schreiben will.

Gefunden habe ich z.B. das hier: 
http://www.mycsharp.de/wbb2/thread.php?postid=243155 (Quellcode fast 
ganz am Ende der Seite - hab leider nicht rausgefunden, wie ich dort 
einen einzelnen Beitrag verlinke).

Probleme hierbei:

1.) ich weiß nicht, wo ich die public class MyAppender deklarieren soll, 
ich habs jetzt auf Verdacht mal in die Program.cs mit reingeschrieben 
und versucht anzupassen.

2.) Alle was ich zu dem Thema gefunden habe, auch das verlinkte, 
schreibt nicht in das MainForm, sondern öffnet ein eigenes, neues 
Fenster. Sei es eine spezielle Form, oder eine Message Box.

Eigentlich möchte ich nix anders, als mit dem Appender eine Methode im 
MainWindow anzusprechen, aber dazu müsste der Appender die Instanz des 
MainWindows kennen.

Hat jemand eine Idee, nen Kniff, wie ich das hinbekommen könnte?

von Matthias S. (da_user)


Lesenswert?

argh Falsches Forum erwischt, könnte ein Mod den Thread in die 
PC-Programmierung schieben?

von R. Rebentrost (Gast)


Lesenswert?

Matthias S. schrieb:

> Probleme hierbei:
>
> 1.) ich weiß nicht, wo ich die public class MyAppender deklarieren soll,
> ich habs jetzt auf Verdacht mal in die Program.cs mit reingeschrieben
> und versucht anzupassen.

In einer eigenen Datei (bei einem komplexen Projekt evtl. wiederum in 
einem Unterordner für Appender oder generell fürs Logging).

> Eigentlich möchte ich nix anders, als mit dem Appender eine Methode im
> MainWindow anzusprechen, aber dazu müsste der Appender die Instanz des
> MainWindows kennen.

Das Problem bei den Appendern in log4net ist, dass du dem Konstruktor 
keine eigenen Parameter übergeben kannst. Mit Propertys funktioniert es 
auch nicht, da diese nur für statische Daten vorgesehen sind, die man in 
der Config-Datei ablegt.

> Hat jemand eine Idee, nen Kniff, wie ich das hinbekommen könnte?

1.
"Hack": In log4net.GlobalContext.Properties etwas hineinwerfen 
(muss/sollte keine direkte Referenz auf Fenster oder Control sein, 
sondern eher ein Objekt als "Zwischenhändler") und im Appender auslesen. 
Ist aber nur so eine (nicht besonders schöne) Idee und ungetestet.

2.
Der Appender sucht eigenständig das Fenster bzw. Control (über 
Application.OpenForms).

http://stackoverflow.com/questions/14114614/configuring-log4net-textboxappender-custom-appender-via-xml-file

Unten findest du die neueste Version.

von Matthias S. (da_user)


Lesenswert?

Hi,

ich habe das jetzt über ein Singleton gelöst. Mal ein paar Codezeilen:

AppenderHelper.cs
1
namespace Namespace
2
{
3
    public class AppenderHelper
4
    {
5
        private static AppenderHelper _Instance = null;
6
7
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
8
9
        public MainWindow mw  { get; set; }
10
11
        public void writeLog(string text)
12
        {
13
            if (mw != null)
14
            {
15
                mw.writeLog(text);
16
            }
17
        }
18
19
        private AppenderHelper() { }
20
21
        public static AppenderHelper Instance
22
        {
23
            get
24
            {
25
                if (_Instance == null)
26
                {
27
                    _Instance = new AppenderHelper();
28
                }
29
                return _Instance;
30
            }
31
        }
32
    }
33
34
    public class MainFormAppender : log4net.Appender.AppenderSkeleton
35
    {
36
        static private LogViewer logViewer;
37
38
        public MainFormAppender()
39
        {
40
        }
41
42
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
43
44
        protected override void Append(log4net.Core.LoggingEvent loggingEvent)
45
        {
46
            AppenderHelper appenderHelper = AppenderHelper.Instance;
47
            appenderHelper.writeLog(loggingEvent.MessageObject.ToString());
48
        }
49
    }
50
}

App.config
1
    <appender name ="MainFormAppender" type="DbEditor4Kodi.MainFormAppender">
2
      <layout type="log4net.Layout.PatternLayout">
3
        <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
4
      </layout>
5
    </appender>

Wichtig ist, dem AppenderHelper natürlich irgendwo die Instanz zum 
MainWindow zu übergeben. Das mache ich gleich im Konstruktur des 
MainWindows:
1
        public MainWindow()
2
        {
3
            InitializeComponent();
4
            AppenderHelper appenderHelper = AppenderHelper.Instance;
5
            appenderHelper.mw = this;
6
        }

Es gibt noch ein "Problem" und ein ToDo das ich auf dem Schirm habe.

ToDo: Multithreadfähige Singleton zu Gemüte führen und dann das obige 
Singleton anpassen

Problem:
Mein Appender in der App.config sieht in Sachen formatierung genauso 
aus, wie die anderen Appender auch:
1
   <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
2
      <layout type="log4net.Layout.PatternLayout">
3
        <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
4
      </layout>
5
    </appender>

Ich bekomme von dem log4net in der VS-Console alle möglichen Details 
angezeigt, eben die, die mit dem Layout definiert sind. Bei meinem 
Appender bekomme ich nur den von mir an den Logger übergebenen Text 
angezeigt.

Versuchsweise habe ich mal
1
appenderHelper.writeLog(loggingEvent.MessageObject.ToString());
 durch
1
appenderHelper.writeLog(loggingEvent.RenderedMessage.ToString());
 ersetzt, Ergebnis bleibt aber das gleiche.

Kann mir da evtl. nochmal jemand helfen?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.