WinRT C #: Unable to save UnhandledException for storage

I am working on WinRT. If an unhandled exception is thrown, I want to write the message text to the repository. I added an event handler to "App.xaml.cs", see Code.

Excluded, but the last line where the file is written worked again → 'exception'!

Why? Any idea?

public App() { this.InitializeComponent(); this.Suspending += OnSuspending; this.UnhandledException += App_UnhandledException; } async void App_UnhandledException(object sender, UnhandledExceptionEventArgs e) { StorageFolder folder = Windows.Storage.ApplicationData.Current.LocalFolder; StorageFile file= await folder.CreateFileAsync("crash.log",CreationCollisionOption.OpenIfExists); await FileIO.AppendTextAsync(file, e.Message); // <----- crash again ----- } 

thanks

Solar

+4
source share
3 answers

I was wondering the same thing and stumbled upon it quite early in my search. I understood the method, I hope it will be useful for someone else.

The problem is that await returns UI flow control and application crashes. You need a respite, but there is no real way to get it.

My solution is to use the settings repository. I assume that most people who want to do this want to do something in LittleWatson style, so the code here was changed for your convenience http://blogs.msdn.com/b/andypennell/archive/2010/11/01/ error-reporting-on-windows-phone-7.aspx :

 namespace YourApp { using Windows.Storage; using Windows.UI.Popups; using System; using System.Collections.Generic; using System.Text; using System.Threading.Tasks; public class LittleWatson { private const string settingname = "LittleWatsonDetails"; private const string email = "mailto: ?to=you@example.com &subject=YourApp auto-generated problem report&body="; private const string extra = "extra", message = "message", stacktrace = "stacktrace"; internal static void ReportException(Exception ex, string extraData) { ApplicationData.Current.LocalSettings.CreateContainer(settingname, Windows.Storage.ApplicationDataCreateDisposition.Always); var exceptionValues = ApplicationData.Current.LocalSettings.Containers[settingname].Values; exceptionValues[extra] = extraData; exceptionValues[message] = ex.Message; exceptionValues[stacktrace] = ex.StackTrace; } internal async static Task CheckForPreviousException() { var container = ApplicationData.Current.LocalSettings.Containers; try { var exceptionValues = container[settingname].Values; string extraData = exceptionValues[extra] as string; string messageData = exceptionValues[message] as string; string stacktraceData = exceptionValues[stacktrace] as string; var sb = new StringBuilder(); sb.AppendLine(extraData); sb.AppendLine(messageData); sb.AppendLine(stacktraceData); string contents = sb.ToString(); SafeDeleteLog(); if (stacktraceData != null && stacktraceData.Length > 0) { var dialog = new MessageDialog("A problem occured the last time you ran this application. Would you like to report it so that we can fix the error?", "Error Report") { CancelCommandIndex = 1, DefaultCommandIndex = 0 }; dialog.Commands.Add(new UICommand("Send", async delegate { var mailToSend = email.ToString(); mailToSend += contents; var mailto = new Uri(mailToSend); await Windows.System.Launcher.LaunchUriAsync(mailto); })); dialog.Commands.Add(new UICommand("Cancel")); await dialog.ShowAsync(); } } catch (KeyNotFoundException) { // KeyNotFoundException will fire if we've not ever had crash data. No worries! } } private static void SafeDeleteLog() { ApplicationData.Current.LocalSettings.CreateContainer(settingname, Windows.Storage.ApplicationDataCreateDisposition.Always); var exceptionValues = ApplicationData.Current.LocalSettings.Containers[settingname].Values; exceptionValues[extra] = string.Empty; exceptionValues[message] = string.Empty; exceptionValues[stacktrace] = string.Empty; } } } 

To implement it, you need to do the same thing as the link above, but provide the data here if the URL is ever omitted:

App.xaml.cs Constructor (BEFORE calling this.InitializeComponent() ):

 this.UnhandledException += (s, e) => LittleWatson.ReportException(e.Exception, "extra message goes here"); 

Obviously, if you already have an UnhandledException method, you can challenge LittleWatson there.

If you are using Windows 8.1, you can also add a call related to navigation. This should be on a real page (usually MainPage.xaml.cs or on any other page):

xx.xaml.cs Constructor (any page):

 rootFrame.NavigationFailed += (s, e) => LittleWatson.ReportException(e.Exception, "extra message goes here"); 

Finally, you need to ask the user if they want to send an email when you reopen the application. In the default page constructor for your application (default: the App.xaml.cs page initializes):

 this.Loaded += async (s, e) => await LittleWatson.CheckForPreviousException(); 

Or add a call to the OnLoad method if you are already using it.

+4
source

In this situation, await can be freely translated to "do this work in another thread and continue what you did while you wait for the end." Given that what your application was doing is crashing, you probably don't want it to continue to do this until you complete the problem registration. In this case, I suggest running the IO file synchronously.

0
source

It may be too late for the original question, but ...

as @Hans Passant suggested, avoiding await (i.e. by running FileIO.AppendTextAsync() synchronously), also seconded by @Jon, I would choose this rather than the relatively heavy code for LittleWatson. Since the application is still in some kind of error transmission state (this should be a rare occurrence), I would not block synchronous (due to removal of waiting) as the main drawback.

Leaving the synchronous option one way, the following await implementation worked for me:

Modify await FileIO.AppendTextAsync(file, e.Message); on the:

 Task task = LogErrorMessage(file, e.Message) task.Wait(2000); // adjust the ms value as appropriate 

...

 private async Task LogErrorMessage(StorageFile file, string errorMessage) { await FileIO.AppendTextAsync(file, errorMessage); // this shouldn't crash in App_UnhandledException as it did before } 
0
source

All Articles