Windows Phone From Scratch
Jon Galloway and I have been working together on The Full Stack project. This week, we’ve been banging our heads together trying to figure out why our Windows Phone application crashes on testing when submitted to the Marketplace, yet it tests fine on my PC and on my phone.
We finally decided that we needed some debugging information from when it crashes and that the best way to do that would be to catch the exception that we are presuming is being thrown, and get a stack trace. But how to get that to us?
Catching the exception and showing it locally wasn’t a terribly hard problem to solve. In App.xaml.cs there is a method Application_UnhandledException. We opted to create an error message based on the exception and first display it in a message box.
The first hurdle is that the argument to Application_UnhandledException is not the exception, but rather is an ApplicationUnahandledExceptionEventArg. You can get to the exception, however, through its ExceptionObject property.
The second hurdle was that we couldn’t open a MessageBox because we were on the wrong thread, and you can’t just call Dispatcher.BeginInvoke because you are not in a view. Fortunately, you can call Deployment.Current.Dispatcher.BeginInvoke, which is what we did,
Deployment.Current.Dispatcher.BeginInvoke( () => { string errorMsg = string.Format( "Exception caught. Message: {0} \r\nTrace: {1}", e.ExceptionObject.Message, e.ExceptionObject.StackTrace ); System.Windows.MessageBox.Show( errorMsg ); SendEmailOfException( errorMsg ); } );
This shows the error and the stack trace in a MessageBox, but that is of limited utility when the error is happening at the tester’s location and not our own. Thus, we added the call to our method SendEmailOfException.
The method SendEmailOfException uses the Email launcher to pass the error message (and stack trace) to the email application, pre-filling in the To field and the Subject field as well. All that is needed is an instance of EmailComposeTask. We invoke the actual dispatch to email by calling Show(),
private static void SendEmailOfException(string msg) { var emailComposeTask = new EmailComposeTask { To = "[email protected]; [email protected]", Subject = "Who Is That Error", Body = msg }; emailComposeTask.Show(); }
It’s great. We put in an exception to test and as soon as the exception was raised the MessageBox opens. Close the MessageBox and the exception appears in the outbound Email. Send it and we instantly received the email in our inbox:
From: Jesse Liberty Sent: Tuesday, April 26, 2011 5:50 PM To: Jesse Liberty; Jon Galloway Subject: Who Is That Error Exception caught. Message: Exception thrown in
loginSucceeded method! Trace: at WhoIsThatWinPhone.View.Authentication.<loginSucceeded>b__0(Object o, FacebookApiEventArgs e) at Facebook.FacebookClient.OnGetCompleted(FacebookApiEventArgs args) at Facebook.FacebookClient.DownloadDataCompleted(Object sender, DownloadDataCompletedEventArgsWrapper e) at Facebook.FacebookClient.<>c__DisplayClass7.<ApiAsync>b__2(String json, Exception ex) at Facebook.FacebookClient.ResponseCallback(IAsyncResult asyncResult, Action`2 callback, Object state) at Facebook.FacebookClient.<>c__DisplayClass7.<ApiAsync>b__4(IAsyncResult ar) at System.Net.Browser.ClientHttpWebRequest.<>c__DisplayClassa.<InvokeGetResponseCallback>b__8(Object state2) at System.Threading.ThreadPool.WorkItem.doWork(Object o) at System.Threading.Timer.ring()
Note: Jon is writing this up for his blog as well. Be sure to check it out.
When the StackTrace is null, which is what I am seeing in my code, can you get the stack trace from somewhere else?
If I put a messagebox.show call without the dispatcher.begininvoke, the messagebox works, and the email works, but it throws me in an endless loop of an unhandled exception. It’s almost as if the unhandled exception is now handled by my code, so the program keeps running, and when it is reactivated, it recreates my “unhandled” exception. Granted, I put my exception causing code in the loaded event, but there should be a way to break out of this.
I must be missing something. I put the dispatcher.begininvoke into the Application_UnhandledException method, and added the method for sending the email, and stuck a line in my program that causes an exception, and when debugging, the program just goes right over this code, and doesn’t do anything but close the program. Yeah, I’m pretty much a noob.
Thanks for the snippet, I shall use them. However, what puzzles me is won’t the app crash out and kill the dispatcher before the code is invoked?
I do exactly this with my apps and have had some error emails from end-users.
Don’t expect any emails from the marketplace testers however. They’ll just fail your app and say it had an exception in the report, but in my experience they never send the email with the details in it to you.
-dave
Hi,
do not use email, where do u put your Jesse Liberty’s mail password ?
just set up a server to receive any error message, then use the server to email it to you
What happens if an email account hasn’t been setup on the phone?
Hey Jesse,
Andy Pennell actually created what he calls “Little Watson”, a nice user friendly exception catching utility, if the application crashes, it will record it in ISO Storage and then when the user goes back into the app, it’ll prompt the user to send off the stack trace – check it out http://blogs.msdn.com/b/andypennell/archive/2010/11/01/error-reporting-on-windows-phone-7.aspx
ChrisNTR