- Prerequisites
- The Silverlight Common Language Runtime
- Setting Up a Silverlight Debugging Session
- Debugging the Exception
- Summary
Debugging the Exception
Remember that the debugger stopped execution due to an exception being thrown, and the debugger also gave very minimal information about the exception (such as exception code)? Is it possible to get more detailed information such as the managed code call stack? There are a couple of different ways to get that information. Because the debugger stopped execution at the point of the exception being thrown, we can use the ClrStack command to dump out the call stack of the managed thread:
0:004> !ClrStack OS Thread Id: 0x3b84 (4) ESP EIP 0208f630 75c89617 [HelperMethodFrame: 0208f630] 0208f6d0 040d03e7 SampleApp.MainPage.Button1_Click(System.Object, System.Windows.RoutedEventArgs) 0208f6e8 01952e05 System.Windows.Controls.Primitives.ButtonBase.OnClick() 0208f700 01952d08 System.Windows.Controls.Button.OnClick() 0208f710 01952c35 System.Windows.Controls.Primitives.ButtonBase. OnMouseLeftButtonUp(System.Windows.Input.MouseButtonEventArgs) 0208f720 01952b99 System.Windows.Controls.Control. OnMouseLeftButtonUp(System.Windows.Controls.Control, System.EventArgs) 0208f730 041239cd MS.Internal.JoltHelper.FireEvent(IntPtr, IntPtr, Int32, System.String) 0208f90c 587417b0 [GCFrame: 0208f90c] 0208f9c8 587417b0 [ContextTransitionFrame: 0208f9c8] 0208fac0 587417b0 [UMThkCallFrame: 0208fac0]
Here we can see that the top part of the call stack corresponds to a button click event handler, which should give us an indication to look closer at the event handler source code for any abnormalities. How can we verify that the exception being thrown is indeed related to this call stack? We can use the threads command, which will output each running managed thread in the process as well as any exceptions associated with the thread:
0:004> !threads ThreadCount: 3 UnstartedThread: 0 BackgroundThread: 3 PendingThread: 0 DeadThread: 0 Hosted Runtime: yes PreEmptive GC Alloc Lock ID OSID ThreadOBJ State GC Context Domain Count APT Exception 4 1 3b84 03d82078 220 Enabled 0458d048:0458dfe8 03dad948 0 STA System.Exception (0458d000) 8 2 3bbc 03d9fba0 b220 Enabled 00000000:00000000 03d76940 0 MTA (Finalizer) 9 3 3bc0 03da0978 1220 Enabled 00000000:00000000 03d76940 0 Ukn
Here we can see that the thread with an identifier of 4 (matching our previous call stack output) has an exception recorded on it (System.Exception). To get further details on the exception, we can use the pe command, which prints out more detailed information about the exception specified.
0:004> !pe 0458d000 Exception object: 0458d000 Exception type: System.Exception Message: Something bad happened! InnerException: <none> StackTrace (generated): <none> StackTraceString: <none> HResult: 80131500
The message associated with the exception states Something bad happened!. We now have the necessary information (call stack and detailed exception) to take a look at the source code to see if we can spot the bug. Because the top part of the call stack indicated that the exception was thrown in the Button1_Click event handler, we can take a look at the method to spot any abnormalities:
private void Button1_Click(object sender, RoutedEventArgs e) { throw new Exception("Something bad happened!"); }
From the source code, we can very clearly spot the problem because the event handler responds to each click on the button by throwing an exception with the message Something bad happened!, which also nicely corresponds to our debug session.
While the source code illustrated is very contrived and simple, it serves to illustrate how Debugging Tools for Windows can be used to perform efficient root cause analysis. Tough problems such as resource constraints and out-of-memory exceptions can all be debugged in Silverlight using the powerful SOS debugger extension using commands such as dumpheap, eeheap, finalizequeue, and more.