LittleWatson: Windows Phone アプリのクラッシュ状況をレポートしてもらう方法

Error Reporting on Windows Phone 7 という記事があります。こちらに、LittleWatsonの実装例が掲載されています。

https://blogs.msdn.com/b/andypennell/archive/2010/11/01/error-reporting-on-windows-phone-7.aspx

この記事からソースを引用する形で、アプリへの組み込みを紹介します。

まずは、LittleWatsonの本体です。単純なクラスです。

// LittleWatson.cs

using System;
using System.Windows;
using System.IO.IsolatedStorage;
using System.IO;
using Microsoft.Phone.Tasks;

namespace YourApp // 作成するアプリに合わせて変更してください。
{
    public class LittleWatson
    {
        const string filename = "LittleWatson.txt";

        internal static void ReportException(Exception ex, string extra)
        {
            try
            {
                using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    SafeDeleteFile(store);
                    using (TextWriter output = new StreamWriter(store.CreateFile(filename)))
                    {
                        output.WriteLine(extra);
                        output.WriteLine(ex.Message);
                        output.WriteLine(ex.StackTrace);
                    }
                }
            }
            catch (Exception)
            {
            }
        }

        internal static void CheckForPreviousException()
        {
            try
            {
                string contents = null;
                using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    if (store.FileExists(filename))
                    {
                        using (TextReader reader = new StreamReader(store.OpenFile(filename, FileMode.Open, FileAccess.Read, FileShare.None)))
                        {
                            contents = reader.ReadToEnd();
                        }
                        SafeDeleteFile(store);
                    }
                }
                if (contents != null)
                {
                    if (MessageBox.Show("A problem occurred the last time you ran this application. Would you like to send an email to report it?", "Problem Report", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
                    {
                        EmailComposeTask email = new EmailComposeTask();
                        email.To = "someone@example.com";  // レポートを受け取りたいメールアドレスを指定します
                        email.Subject = "YourAppName auto-generated problem report";
                        email.Body = contents;
                        SafeDeleteFile(IsolatedStorageFile.GetUserStoreForApplication()); // line added 1/15/2011
                        email.Show();
                    }
                }
            }
            catch (Exception)
            {

            }
            finally
            {
                SafeDeleteFile(IsolatedStorageFile.GetUserStoreForApplication());
            }
        }

        private static void SafeDeleteFile(IsolatedStorageFile store)
        {
            try
            {
                store.DeleteFile(filename);
            }
            catch (Exception ex)
            {
            }
        }
    }
}

 

続いて、例外を記録する処理をApp.xaml.csに仕込みます。黄色でハイライトした部分が追加のコードです。

        // ナビゲーションに失敗した場合に実行されるコード
        private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            LittleWatson.ReportException(e.Exception, DateTime.Now.ToString()+"> NavigationFailed:"+e.Uri.ToString());
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // ナビゲーションに失敗しました。デバッガーで中断します。
                System.Diagnostics.Debugger.Break();
            }
        }

        // ハンドルされない例外の発生時に実行されるコード
        private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
        {
            LittleWatson.ReportException(e.ExceptionObject, DateTime.Now.ToString() + "> UnhandledException");
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // ハンドルされない例外が発生しました。デバッガーで中断します。
                System.Diagnostics.Debugger.Break();
            }
        }

最後に、アプリ起動時に表示されるページの読み込み時に、前回発生した例外をチェックします。
前回にクラッシュしていれば、メッセージを表示し、メールを作成します。

        public MainPage()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(MainPage_Loaded);
           
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            LittleWatson.CheckForPreviousException();
        }

実行例:

 

メールの例:

--------

2012/07/19 19:48:36> UnhandledException

DivideByZeroException
   at TweetsSearch.MainPage.button1_Click(Object sender,
RoutedEventArgs e)
   at System.Windows.Controls.Primitives.ButtonBase.OnClick()
   at System.Windows.Controls.Button.OnClick()
   at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs
e)
   at System.Windows.Controls.Control.OnMouseLeftButtonUp(Control
ctrl, EventArgs e)
   at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr
unmanagedObjArgs, Int32 argsTypeIndex, Int32 actualArgsTypeIndex, String
eventName)

Sent from Windows Phone IS12T

--------

LittleWatson、皆さんも活用してはいかがでしょうか。