Question

I'm trying to use a Form with TextBox as an appender for log4net but TextBox simply do not append text. I see, that AppendText method is called (from UI thread), property Text is changed, but at some time appended value just dissapearing and Text property is still empty.

I'm not sure, if it is log4net issue, but the problem appears only with logs.

Application start-up and form (InvokeIfRequired is very common extension from here: Automating the InvokeRequired code pattern):

public partial class FormMain : Form, IAppender
{
    readonly ILog log;

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        XmlConfigurator.Configure();

        Application.Run(new FormMain());
    }
    public FormMain()
    {
        log = LogManager.GetLogger(typeof(FormMain));

        InitializeComponent();
    }

    public void DoAppend(LoggingEvent le)
    {
        tbLog.AppendText("This msg is NOT shown");

        tbLog.InvokeIfRequired(() =>
            {
                // NOT SHOWN
                tbLog.AppendText(string.Format("{0:yyyyMMdd HH:mm:ss.fff}> [{1}] [{2}] {3}", le.TimeStamp, le.LoggerName, le.Level, le.MessageObject));
            });
    }

    private void bTestLog_Click(object sender, EventArgs e)
    {
        tbLog.AppendText("This msg is shown");

        log.Debug("Test logs");
    }
}

App.config:

<?xml version="1.0"?>
<configuration>

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

  <log4net>
    <appender name="FileAppender" type="log4net.Appender.FileAppender,log4net">
      <file value="mylogfile.txt" />
      <appendToFile value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
      </layout>
    </appender>

    <appender name="FormMain" type="Client.FormMain,Client" />

    <root>
      <level value="DEBUG"/>
      <appender-ref ref="FormMain"/>
    </root>
  </log4net>

</configuration>

AssemblyInfo.cs:

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

After clicking the button bTestLog only one message appears on tbLog: "This msg is shown"

UPD I've monitored Text property of tbLog and found it very strange. After first appending, as expected, it is "This msg is shown". But when program enters DoAppend method, it's empty. Further appends change it as expected, but when back to bTestLog_Click it's "This msg is shown" again!

Was it helpful?

Solution

Okay, I think I've got it.

I strongly suspect that this:

<appender name="FormMain" type="Client.FormMain,Client" />

... is getting log4net to create a new instance of FormMain. So you've got one instance being shown, but there's another form which isn't being shown, but is receiving append calls.

You should be able to see that in the debugger - if you put breakpoints in both DoAppend and bTestLog_Click, you'll see the instance that the methods are being invoked on being different.

I don't know the best way of hooking log4net into an existing object, but you may find that you can just programmatically add an appender in log4net; you should look at the API for more details.

As an aside, I'd probably separate the concerns of "being an appender" and "being a form" - I'd create an implementation of IAppender which appends to a text box which is provided in its constructor, and then pass the relevant text box from the form when you construct the appender. That's a slightly different matter though :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top