[ Für Details zur Fehlerbehandlung in .NET im Allgemeinen, unter Berücksichtigung von von multi-threaded Programmierung (insbesondere mit Task und Await) siehe meinen Artikel „Lass da mal was sein“ im dotnetpro Magazin 3/2013.
Für Details zur Fehlerbehandlung in UWP-Apps siehe meinen Artikel „Was war da los?“ im dotnetpro Magazin 12/2016. ]
This post is the result of my experiments with handling unexpected errors in UWP-Apps.
For my approach about tracing see Tracing for UWP-Apps
It is debatable if showing information about unexpected exceptions to users is good idea. I have had Mail, Translator, Calculator, the Store app and other UWP-Apps abort without any feedback on crash or at restart. I personally find it annoying when apps simply disappear without any hint. The „little Watson“ solution of displaying error info on the next app start feels weird to me. Both behaviors doe not conform with common user expectations.
If crash error details can be helpful for end users depends on the app type and the target audience. For enterprise apps I know from long experience that error notifications (even with deep technical infos) are definitely helpful. Users are often able to circumvent problems and keep working with defective apps without even contacting support (while support might have been made aware of the problem automatically in the background…).
Options to inform users about unexpected exceptions are:
- Never notify users about exceptions.
- Show dialog in App.UnhandledException
- Show dialog on next app start.
- Show exception details like Message and HResult
- Show „Sorry…“ only.
This following code sample implements the main options, configurable via _notifyUserAboutCrash.
Some implementation notes:
- UnhandledExceptionEventArgs.Exception returns useful values only on first access.
See Why does UnhandledExceptionEventArgs.Exception return useful info only on first access?
As a workaround one can assign it to a local variable and use this subsequently - Async calls in UnhandledException only work after setting e.Handled=True.
UnhandledException does not offer a deferral. - One e.Handled has been set to True setting it to False again does not re-enable automatic app abort. Thus the sample re-throws the exception to make the app crash.
- Under the debugger the sample only works properly with the advanced compile option
DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION.
Without this async calls in UnhandledException throw. - The sample uses my custom trace class.
- I am configuring HockeyApp without WindowsCollectors.UnhandledException.
This disables automatic exception tracking and allows to explicitly use TrackException when desired.
Exception details
The exception details available via UnhandledExceptionEventArgs are more detailed in debug mode then in release mode. Sometimes e.Message contains more details then e.Exception.Message. In debug mode it contains the start of the StackTrace.

Infos provided by UnhandledExceptionEventArgs
Sample implementation
Enum NotifyUserAboutCrash OnError OnNextStart Never End Enum Const _notifyUserAboutCrash As NotifyUserAboutCrash = NotifyUserAboutCrash.OnError Sub New() AddHandler TaskScheduler.UnobservedTaskException, AddressOf TaskScheduler_UnobservedTaskException Trace.Init(TraceTarget.Debug Or TraceTarget.BufferedFile, TraceLevel.Debug) HockeyClient.Current.Configure(“<your App ID>”, New TelemetryConfiguration() With {.Collectors = WindowsCollectors.Metadata}). SetExceptionDescriptionLoader( Function(ex As System.Exception) Return GetBaseExceptionMessage(ex) End Function) End Sub Protected Overrides Async Sub OnLaunched(e As Windows.ApplicationModel.Activation.LaunchActivatedEventArgs) ... If _notifyUserAboutCrash = NotifyUserAboutCrash.OnNextStart Then Await ProblemReporter.NotifyLastExToUserIfExisting() End If ... End Sub Private Shared _isAborting As Boolean = False Private Async Sub App_UnhandledException(sender As Object, e As UnhandledExceptionEventArgs) Handles Me.UnhandledException If _isAborting Then Return 'Must store e.Exception in local variable because it returns useful values on first access only ' Even watching the value in debugger destroys it. Never set a breakpoint before Trace.Debug()! Dim unhandledEx = New Exception(e.Message, e.Exception) 'Without Handled=True async code does crash ' which forces us to rethrow the ex to abort the app e.Handled = True If HandleRecoverableExceptions(unhandledEx.InnerException) Then Trace.Debug($"Recovered from exception: {unhandledEx.Message}") Await Trace.FlushAsync() Return End If Trace.Error($"Unexpected exception: {unhandledEx.InnerException.ToString}") Await Trace.CompleteAsync() Try ProblemReporter.SaveAsLastException(unhandledEx) HockeyClient.Current.TrackException(unhandledEx.InnerException) HockeyClient.Current.Flush() Catch ex As System.Exception Trace.Error(ex) End Try If _notifyUserAboutCrash = NotifyUserAboutCrash.OnError Then Await ProblemReporter.NotifyExceptionToUserViaMessageDialogAsync(unhandledEx) End If 'reenabling auto crash via e.Handled=False does not work Await ForceAppCrashAsync(unhandledEx) End Sub Private Shared Async Function ForceAppCrashAsync(unhandledEx As Exception) As Task Trace.Fatal("!!! aborting") Await Trace.CompleteAsync() _isAborting = True 'Rethrow ex with a StackTrace as if it came form the original location ExceptionDispatchInfo.Capture(unhandledEx.InnerException).Throw() End Function Private Function HandleRecoverableExceptions(ex As System.Exception) as Boolean Select Case True Case TypeOf (ex) Is MyCustomException Return True 'Case TypeOf (unhandledException) Is ??? Case Else Return False End Select End Function Private Async Sub TaskScheduler_UnobservedTaskException(sender As Object, e As UnobservedTaskExceptionEventArgs) 'UnobservedTaskExceptions get tracked by HockeyApp v4.1.1+ Dim ex = e.Exception Trace.Warn($"TaskScheduler_UnobservedTaskException: {ex.ToString}") Await Trace.FlushAsync HockeyClient.Current.TrackException(ex) HockeyClient.Current.Flush() e.SetObserved() End Sub

Error dialog from UnhandledException

Error dialog on next app start