Introduction
Like other programmers I use a lot of try...catch
statements in my code to catch exceptions, help debug, and avoid crashs. For that reason, I put a lot of Console.Error.WriteLine(...)
in my catch blocks to keep a trace of the exceptions that occured. But when I release an app, even if exceptions should not happen anymore, it is always useful to have some kind of system to keep a trace of raised exceptions. The following code demonstrates a solution to keep a trace of those exceptions in a XML file.
The ErrorLogWriter class
This class inherits from the standard System.IO.TextWriter class. Subclassing TextWriter allows us to use our custom ErrorLogWriter class with Console.Error.
The trick is to create an ErrorLogWriter instance and then call Console.SetOut(...)
with this instance as a parameter.
Then every Console.Error.WriteLine(...)
call will be redirected to our ErrorLogWriter instance and a XML entry added in the file.
I tried to keep the code as simple as possible. So many features can be added, like handling more TextWriter.Write
methods or providing even more informations in the ErrorLogWriter.WriteLine
function.
To give this article some additional value, I also gave a way to get the calling class and method using the stack trace and reflection. I also added an attribute to the ErrorLogWriter.WriteLine
function to synchronize it in multi-threaded programs (equivalent to the lock(this)
keyword).
using System;
using System.IO;
using System.Xml;
using System.Text;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace ErrorLogger.Utility{
public class ErrorLogWriter:TextWriter{
private bool Disposed;
private XmlTextWriter Writer;
public ErrorLogWriter(string FilePath){
Disposed=false;
Writer=new XmlTextWriter(FilePath,Encoding.Unicode);
Writer.Formatting=Formatting.Indented;
Writer.WriteStartDocument();
Writer.WriteStartElement("error");
Writer.Flush();
}
~ErrorLogWriter(){
Dispose(false);
}
protected override void Dispose(bool Disposing){
if(!Disposed){
if(Disposing){
}
Writer.Close();
Writer=null;
Disposed=true;
base.Dispose(Disposing);
}
}
public override void Close(){
Writer.WriteEndElement();
Writer.WriteEndDocument();
Writer.Flush();
Dispose(true);
GC.SuppressFinalize(this);
}
public override Encoding Encoding{
get{
return(Encoding.Unicode);
}
}
[MethodImpl(MethodImplOptions.Synchronized)]
public override void WriteLine(string Txt){
Writer.WriteStartElement("event");
Writer.WriteStartElement("time");
Writer.WriteString(DateTime.Now.ToLongTimeString());
Writer.WriteEndElement();
Writer.WriteStartElement("class");
Writer.WriteString(new StackTrace().GetFrame(2).GetMethod().ReflectedType.FullName);
Writer.WriteEndElement();
Writer.WriteStartElement("method");
Writer.WriteString(new StackTrace().GetFrame(2).GetMethod().ToString());
Writer.WriteEndElement();
Writer.WriteStartElement("text");
Writer.WriteString(Txt);
Writer.WriteEndElement();
Writer.WriteEndElement();
Writer.Flush();
}
}
}
The test class
Here is an example of how to use the ErrorLogWriter class. Of course, all this code is available in the zip file.
using System;
using System.IO;
using ErrorLogger.Utility;
namespace ErrorLogger{
class Test{
[STAThread]
static void Main(string[] args){
ErrorLogWriter Err=new ErrorLogWriter(Directory.GetCurrentDirectory()+@"\Error.xml");
Console.SetError(Err);
Console.Error.WriteLine("Here is my first error !");
Console.Error.WriteLine("I should write this inside a catch(exception) statement...");
newFunction();
Err.Close();
Console.Out.WriteLine("Error file created. Press a key...");
Console.Read();
}
private static void newFunction(){
Console.Error.WriteLine("Look ! I am inside a function !");
}
}
}
Conclusion
I hope this article will help some people and will be useful for somebody.
Here you have basic concepts to understand how to subclass the TextWriter class, how to redirect the standard Console.Error stream and some tips about reflection and stack trace.
It is also worth to add that you can customize this code to redirect other streams like Console.In or Console.Out.
Happy Coding !!!