using System; using System.Windows.Forms; using log4net; using log4net.Appender; using log4net.Repository.Hierarchy; public class TextBoxAppender : IAppender { private TextBox _textBox; private readonly object _lockObj = new object(); public TextBoxAppender(TextBox textBox) { var frm = textBox.FindForm(); if(frm==null) return; frm.FormClosing += delegate { Close(); }; _textBox = textBox; Name = "TextBoxAppender"; } public string Name { get; set; } public static void ConfigureTextBoxAppender(TextBox textBox) { var hierarchy = (Hierarchy)LogManager.GetRepository(); var appender = new TextBoxAppender(textBox); hierarchy.Root.AddAppender(appender); } public void Close() { try { // This locking is required to avoid null reference exceptions // in situations where DoAppend() is writing to the TextBox while // Close() is nulling out the TextBox. lock (_lockObj) { _textBox = null; } var hierarchy = (Hierarchy)LogManager.GetRepository(); hierarchy.Root.RemoveAppender(this); } catch { // There is not much that can be done here, and // swallowing the error is desired in my situation. } } public void DoAppend(log4net.Core.LoggingEvent loggingEvent) { try { if (_textBox == null) return; // For my situation, this quick and dirt filter was all that was // needed. Depending on your situation, you may decide to delete // this logic, modify it slightly, or implement something a // little more sophisticated. if(loggingEvent.LoggerName.Contains("NHibernate")) return; // Again, my requirements were simple; displaying the message was // all that was needed. Depending on your circumstances, you may // decide to add information to the displayed message // (e.g. log level) or implement something a little more // dynamic. var msg = string.Concat(loggingEvent.RenderedMessage, "\r\n"); lock (_lockObj) { // This check is required a second time because this class // is executing on multiple threads. if (_textBox == null) return; // Because the logging is running on a different thread than // the GUI, the control's "BeginInvoke" method has to be // leveraged in order to append the message. Otherwise, a // threading exception will be thrown. var del = new Action<string>(s => _textBox.AppendText(s)); _textBox.BeginInvoke(del, msg); } } catch { // There is not much that can be done here, and // swallowing the error is desired in my situation. } } }
To wirer this appender up to a TextBox, simply use the following code.
//Where "LoggingTextBox" is a TextBox having the following settings: //LoggingTextBox.Multiline = true; //LoggingTextBox.ReadOnly = true; //LoggingTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; TextBoxAppender.ConfigureTextBoxAppender(LoggingTextBox);
It works for me thanx mate
ReplyDeleteThank you for sharing, nice solution
ReplyDelete