Find where the original exception was originally thrown using the Visual Studio C # debugger?

The usual advice when rebuilding an exception is to use the throw; statement throw; so that the original stack trace is preserved. ( Example )

However, when I try this simple example, the Visual Studio debugger does not show the original stack trace.

 namespace ExceptionTest { class Program { static void ThrowException() { throw new System.Exception(); // The line that I WANT the debugger to show. } static void Main(string[] args) { try { ThrowException(); } catch (System.Exception) { System.Console.WriteLine("An exception was thrown."); throw; // The line that the debugger ACTUALLY shows. } } } } 

How can I use a debugger to find the source of the exception?

+7
source share
5 answers

If you are using Visual Studio 2010 Ultimate, use IntelliTrace .

It keeps a record of all selected exceptions and allows you to "debug back in time" to see parameters, threads and variables during each throw.

(taken from Chris Schmich answered a similar question .)

+5
source

Your best option is to ask Visual Studio to break the original exception, rather than returning to it from the stack trace. For this:

1) Click on the "Debug" menu item 2) Click on "Exceptions ..." 3) Select "Exceptions for the total runtime of the language" - "Abandoned"

With this approach, you can get more than you really wanted, if there are many exceptions. You can filter which exceptions it breaks by expanding the list of trees.

See image:

enter image description here

+10
source

The best solution I have found is writing an Exception column in Debug.Console , and then letting Visual Studio's built-in line of code parser provide navigation.

It was very useful for me to deal with unhandled exceptions in AppDomain and WPF Manager since Visual Studio always breaks too late.

Based on the article about Code Project , I changed it so that it displayed on the console as a single block of text, and not on the -by-line line - which was necessary, I also write entries to the console.

Using

 public void ReportException(Exception exception) { if (Debugger.IsAttached) { DebugHelper.PrintExceptionToConsole(exception); Debugger.Break(); } // ... } 

A source

 public static class DebugHelper { // Original idea taken from the CodeProject article // http://www.codeproject.com/Articles/21400/Navigating-Exception-Backtraces-in-Visual-Studio private static readonly string StarSeparator = new String('*', 80); private static readonly string DashSeparator = new String('-', 80); private const string TabString = " "; /// <summary> /// Prints the exception using a format recognized by the Visual Studio console parser. /// Allows for quick navigation of exception call stack. /// </summary> /// <param name="exception">The exception.</param> public static void PrintExceptionToConsole(Exception exception) { using (var indentedTextWriter = new IndentedTextWriter(Console.Out, TabString)) { var indentLevel = 0; while (exception != null) { indentedTextWriter.Indent = indentLevel; indentedTextWriter.Write(FormatExceptionForDebugLineParser(exception)); exception = exception.InnerException; indentLevel++; } } } private static string FormatExceptionForDebugLineParser(Exception exception) { StringBuilder result = new StringBuilder(); result.AppendLine(StarSeparator); result.AppendLineFormat(" {0}: \"{1}\"", exception.GetType().Name, exception.Message); result.AppendLine(DashSeparator); // Split lines into method info and filename / line number string[] lines = exception.StackTrace.Split(new string[] { " at " }, StringSplitOptions.RemoveEmptyEntries) .Select(x => x.Trim()) .Where(x => !String.IsNullOrEmpty(x)) .ToArray(); foreach (var line in lines) { string[] parts = line.Split(new string[] { " in " }, StringSplitOptions.RemoveEmptyEntries); string methodInfo = parts[0]; if (parts.Length == 2) { string[] subparts = parts[1].Split(new string[] { ":line " }, StringSplitOptions.RemoveEmptyEntries); result.AppendLineFormat(" {0}({1},1): {2}", subparts[0], Int32.Parse(subparts[1]), methodInfo); } else result.AppendLineFormat(" {0}", methodInfo); } result.AppendLine(StarSeparator); return result.ToString(); } } 

To use the above, as is, you will also need the extension method below and add the System.CodeDom.Compiler namespace to IndentedTextWriter .

Extension method

 /// <summary> /// Appends the string returned by processing a composite format string followed by the default line terminator. /// </summary> /// <param name="sb">The StringBuilder.</param> /// <param name="format">The format.</param> /// <param name="args">The args.</param> public static void AppendLineFormat(this StringBuilder sb, string format, params object[] args) { sb.AppendFormat(format, args); sb.AppendLine(); } 
+1
source

You can use the DebuggerNonUserCode attribute.

See http://blogs.msdn.com/b/jmstall/archive/2007/02/12/making-catch-rethrow-more-debuggable.aspx

An example is as follows:

 namespace ExceptionTest { class Program { static void ThrowException() { throw new System.Exception(); // The line that I WANT the debugger to show. } [DebuggerNonUserCode()] static void Main(string[] args) { try { ThrowException(); } catch (System.Exception) { System.Console.WriteLine("An exception was thrown."); throw; // The line that the debugger ACTUALLY shows. } } } } 
+1
source

By the way, in vb.net you can use exception filters in some situations, for example, when someone knows that he is not very interested in catching an exception - just finding out that this happened. If the code was written in vb.net and a filter was used to catch the exception (perhaps the output itself in the finally block) there would be no โ€œcatch and rethrowโ€ - the cursor would move to the original source exception (as a bonus, vs would interrupt the program flow until how the stack unlocks). Please note that each time a specific exception occurs, you can choose vs trap, regardless of whether it is caught, but sometimes it is only interested in the places where the exception is thrown, and not all.

0
source

All Articles