You can’t be afraid to make errors! You can’t be afraid to be naked before the crowd, because no one can ever master the game of baseball, or conquer it. You can only challenge it.   Lou Brock, In Late Innings, by Roger Angell, 1977

When developing a new application, errors occur. Error handling is built into my apps from the beginning. Sometimes the error is not obvious where it was trigger from. The application may be running in multiple threads or running code during application idle.
The .NET framework includes call stack information with every Exception but the formatting of the Exception is hard to read and has way too much information. Listed below is a small class that walks through all the exceptions and shows a formatted call stack with line numbers from the application. Also, the .NET Framework calls can be shown in the call stack.

The first piece of code shows how to call the class methods.

private void btnMyErrorOnly_Click(object sender, EventArgs e)
{
  try
  {
    throw new ApplicationException("My Error Only Exception");
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.Message + Environment.NewLine +
    PaxArmonia.Error.CallStackInformation.ConstructCallStack(ex),
    "My Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
  }
}

private void btnFullError_Click(object sender, EventArgs e)
{
  try
  {
    throw new ApplicationException("Error with .NET Trace");
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.Message + Environment.NewLine +
    PaxArmonia.Error.CallStackInformation.ConstructCallStack(ex, false),
    "My Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
  }
}

The display dialogs are shown below. The second call shows much more information but rarely do I need this extra information.

Here is the class source code.  The public method calls are highlighted.

using System;
using System.Collections.Generic;
using System.Text;

namespace PaxArmonia.Error
{
public static class CallStackInformation
{
public static string ConstructCallStack(Exception capturedException)
{
return ConstructCallStack(capturedException, true);
}

public static string ConstructCallStack(Exception capturedException, bool fileLineOnly)
{
// See System.Environment.StackTrace for explanation of the construction of the
// StackTrace string.

string result = Environment.NewLine + “Call Stack Trace”;

string exceptionFileName;
foreach (Exception ex in ReverseExceptionList(capturedException))
{
exceptionFileName = ExtractFileFromStackTrace(ex.StackTrace, fileLineOnly);
if (exceptionFileName != string.Empty)
result = result + Environment.NewLine + exceptionFileName;
}

// Find the calling routines
bool done = false;
int stackStart = 1;
while (!done)
{
stackStart++;
System.Diagnostics callStack = new System.Diagnostics.StackFrame(stackStart, true);
if (callStack.GetMethod() == null)
done = true;
else
{
// Build the stack trace to appear the same as the one in the Exception
string stackTrace = ”   at ” + callStack.GetMethod();
if (callStack.GetFileName() != null)
stackTrace = stackTrace + ” in ” + callStack.GetFileName();
if (callStack.GetFileLineNumber() != 0)
stackTrace = stackTrace + “:line ” + callStack.GetFileLineNumber().ToString();

exceptionFileName = ExtractFileFromStackTrace(stackTrace, fileLineOnly);
if (exceptionFileName != string.Empty)
result = result + Environment.NewLine + exceptionFileName;
}
}

return result;
}

private static List ReverseExceptionList(Exception capturedException)
{
List fifoExceptioList = new List();
Exception ex = capturedException;
while (ex != null)
{
fifoExceptioList.Insert(0, ex);
ex = ex.InnerException;
}

return fifoExceptioList;

Tags: