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!
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 :)