In this blog post, we are going to show how to use NP .NET Profiler to capture a memory dump on unhandled exception in Windows Store Applications. You can download the profiler tool from here.

Whenever a Windows Store Application gets terminated due to an unhandled exception, .NET Runtime will log an event with the exception details and complete callstack as shown below.

Click the image for a larger view

eventlog

Most of the time this callstack will help us to determine the location of the unhandled exception. But in few cases, the callstack doesn’t include any application functions, so it is very hard to pinpoint the location of the unhandled exception. And sometimes only with the callstacks information, it is very hard to determine the root cause of the unhandled exception.

Memory dump just before the process termination will not only help us to determine the location of the unhandled exception but it also helps us to determine the root cause of the exception.    

Steps to capture unhandled exception dump

 

  1. Download NP .NET Profiler tool from here
  2. Extract the NPStoreApp.zip file to c:\temp\np folder
  3. Double click on the NPStoreApp.exe
  4. Select the Windows Store Application from the listbox
  5. Set the “Profiler Type” to “Performance Profiler”
  6. Set the “Filter Type” to “Namespace Based Filter”
  7. Set the “Filter Settings” to “Ignore System and Microsoft Namespaces”
  8. In the “Profiler Options” enable the “Capture Unhandled Exception Dump” as shown below

    profilersettings

  9. Click on the “Start Profiling” button. This will launch the application and the profiler will now monitor for unhandled exceptions.
  10. Reproduce the unhandled exception
  11. As soon as the unhandled exception is raised, the application gets terminated and just before termination, profiler captures a full memory dump
  12. The memory dump file is saved to the temp folder. Just click on the “Open Output Folder” button to view the dump file location as shown below

    Click the image for a larger view

    dumpfilelocation

  13.   Now open this memory dump file in WinDBG and execute following commands
    1. !symfix c:\websymbols
    2. .loadby sos clr
    3. !clrstack
    4. !dso
    5. !pe <exception object>
  14. Here is the WinDBG output for these above commands
    1. !clrstack shows the exact callstack as captured in the eventlog
    2. !dso provides the address of the exception object that was not handled
    3. !pe provides the exception details and the callstack that raised the exception
      1. The location of the handled exception is  : TestApp!TestApp.MainPage+<CrashTest>
      2. The root cause of the exception is  : calling UI element from a worker thread

0:022> !clrstack
OS Thread Id: 0x270c (22)
Child SP       IP Call Site   
1191f8d4 0d96588c System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__1(System.Object) 
1191f8dc 0d965846 System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(System.Object) 
1191f8e4 0d9630d7 System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) 
1191f954 0d9629c7 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
1191f968 0d96578a System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() 
1191f97c 0d961884 System.Threading.ThreadPoolWorkQueue.Dispatch()
1191f9cc 0d9616a6 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() 
1191fbf0 63412652 [DebuggerU2MCatchHandlerFrame: 1191fbf0]
0:022> !dso
OS Thread Id: 0x270c (22)
ESP/REG  Object   Name
1191EFDC 03fac65c System.Exception   
 
0:022> !pe 03fac65c
Exception object: 03fac65c
Exception type:   System.Exception
Message:          The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))
InnerException:   <none>
StackTrace (generated):
    SP       IP       Function
    00000000 00000001 Windows_UI_Xaml_64e0000!Windows.UI.Xaml.Controls.Primitives.ToggleButton.get_IsChecked()+0x2
    11BDF18C 0D963892 TestApp!TestApp.MainPage+<CrashTest>d__22.MoveNext()+0x102
    1191F8D4 0D96588C mscorlib!System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__1(System.Object)+0x34
    1191F8DC 0D965846 mscorlib!System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(System.Object)+0x3e
    1191F8E4 0D9630D7 mscorlib!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+0xef
    1191F954 0D9629C7 mscorlib!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+0x17
    1191F968 0D96578A mscorlib!System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()+0x5a
    1191F97C 0D961884 mscorlib!System.Threading.ThreadPoolWorkQueue.Dispatch()+0x1c4
    1191F9CC 0D9616A6 mscorlib!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()+0x6

StackTraceString: <none>
HResult: 8001010e