コード例 #1
0
ファイル: ApplicationUtility.cs プロジェクト: prepare/HexKit
        /// <summary>
        /// Handles the <see cref="Application.DispatcherUnhandledException"/> event.</summary>
        /// <param name="information">
        /// Information about the <see cref="Exception"/> and the current application state, or a
        /// null reference for no available information.</param>
        /// <param name="rulesFile">
        /// The file path to the current scenario rule script, or a null reference if no such file
        /// exists.</param>
        /// <param name="saveScenario">
        /// An optional <see cref="Action{String}"/> delegate that is invoked to save the current
        /// scenario data to an XML file.</param>
        /// <param name="saveSession">
        /// An optional <see cref="Action{String}"/> delegate that is invoked to save the current
        /// session data to an XML file.</param>
        /// <remarks><para>
        /// <b>OnUnhandledException</b> creates a text file describing the error which includes the
        /// specified <paramref name="information"/>. Additionally, up to two debug XML files
        /// containing scenario and session data are created by invoking any of the supplied <see
        /// cref="Action{String}"/> delegates that are not null references.
        /// </para><para>
        /// The user is also asked to e-mail all created files, plus the specified <paramref
        /// name="rulesFile"/> if it exists, to the e-mail address specified by the <see
        /// cref="ApplicationInfo.Email"/> property via Simple MAPI, or if this fails, to send basic
        /// error information to the same address using the Explorer "mailto" method.
        /// </para><para>
        /// Finally, <b>OnUnhandledException</b> terminates the application using <see
        /// cref="Environment.Exit"/> and returns an error code of -1.</para></remarks>

        public static void OnUnhandledException(string information, string rulesFile,
                                                Action <String> saveScenario, Action <String> saveSession)
        {
            // check for original distribution package
            bool original = ApplicationInfo.IsSigned;

            // determine error and debug file names
            string errorFile    = FilePaths.CreateUserPath("FatalError.txt").AbsolutePath;
            string scenarioFile = FilePaths.GetScenarioFile(ScenarioFileType.Debug).AbsolutePath;
            string sessionFile  = FilePaths.GetSessionFile(SessionFileType.Debug).AbsolutePath;

            // create an error e-mail?
            bool wantEmail = false;

            if (original)
            {
                // ask user to create e-mail with attachments
                string message = String.Format(ApplicationInfo.Culture,
                                               Strings.DialogFatalErrorOriginal, errorFile, scenarioFile, sessionFile);

                wantEmail = ShowFatalError(message, null, true);
            }
            else
            {
                // just notify user that files are being saved
                string message = String.Format(ApplicationInfo.Culture,
                                               Strings.DialogFatalErrorModified, errorFile, scenarioFile, sessionFile);

                ShowFatalError(message, null, false);
            }

            // create state information string
            StringBuilder info = new StringBuilder();

            info.AppendFormat("{0} ", ApplicationInfo.Signature);
            info.Append(Environment.NewLine);
            info.AppendFormat("Kynosarges Signature: {0}", original);
            info.Append(Environment.NewLine);
            info.AppendFormat("Public Key Token: {0}",
                              StringUtility.Validate(ApplicationInfo.PublicKeyToken));
            info.Append(Environment.NewLine);
            info.AppendFormat("Home: \"{0}\" ", FilePaths.ApplicationFolder);
            info.Append(Environment.NewLine);
            info.Append(Environment.NewLine);
            info.AppendFormat("{0} ", Environment.OSVersion);
            info.Append(Environment.NewLine);
            info.AppendFormat("{0} ", WindowsUtility.GetMemoryStatus());
            info.Append(Environment.NewLine);
            info.Append(Environment.NewLine);

            // append additional information if specified
            if (!String.IsNullOrEmpty(information))
            {
                info.AppendFormat("{0} ", information);
                info.Append(Environment.NewLine);
            }

            // create subject for e-mail message
            string subject = String.Concat(ApplicationInfo.Signature, " ", Strings.LabelError);

            // collection to hold file attachment data
            List <MapiAddress> files = new List <MapiAddress>();

            try {
                try {
                    // always create error information file
                    files.Add(new MapiAddress(Path.GetFileName(errorFile), errorFile));
                    using (StreamWriter writer = new StreamWriter(errorFile, false, Encoding.UTF8))
                        writer.WriteLine(info.ToString());

                    // attach rule script file if specified
                    RootedPath rulesPath = FilePaths.CreateCommonPath(rulesFile);
                    if (!rulesPath.IsEmpty && File.Exists(rulesPath.AbsolutePath))
                    {
                        files.Add(new MapiAddress(rulesPath.FileName, rulesPath.AbsolutePath));
                    }

                    // create scenario debug file if possible
                    if (saveScenario != null)
                    {
                        saveScenario(scenarioFile);
                        files.Add(new MapiAddress(Path.GetFileName(scenarioFile), scenarioFile));
                    }

                    // create session debug file if possible
                    if (saveSession != null)
                    {
                        saveSession(sessionFile);
                        files.Add(new MapiAddress(Path.GetFileName(sessionFile), sessionFile));
                    }
                }
                catch (Exception e) {
                    // only proceed if user wanted e-mail
                    if (wantEmail)
                    {
                        // ask user to try simpler e-mail format
                        wantEmail = ShowFatalError(Strings.DialogFatalErrorSaveMail, e, true);
                        throw; // rethrow to try mailto:
                    }

                    // user declined e-mail, just show error
                    ShowFatalError(Strings.DialogFatalErrorSave, e, false);
                    return; // quit, nothing else to do
                }

                // quit now if user declined e-mail
                if (!wantEmail)
                {
                    return;
                }

                try {
                    // address e-mail to application author
                    MapiAddress recipient = new MapiAddress(
                        ApplicationInfo.Company, ApplicationInfo.Email);

                    // try sending e-mail with attached files
                    MapiMail.SendMail(subject, "", new[] { recipient }, files.ToArray());
                }
                catch (Exception e) {
                    // quit if user cancelled MAPI session
                    MapiException me = e as MapiException;
                    if (me != null && me.Code == MapiException.Abort)
                    {
                        return;
                    }

                    // ask user to try simpler e-mail format
                    wantEmail = ShowFatalError(Strings.DialogFatalErrorMail, e, true);
                    throw; // rethrow to try mailto:
                }
            }
            catch {
                // quit now if user declined e-mail
                if (!wantEmail)
                {
                    return;
                }

                // construct shell command to create e-mail
                string mailto = String.Format(CultureInfo.InvariantCulture,
                                              "mailto:{0}?subject={1}&body={2}", ApplicationInfo.Email, subject, info);

                try {
                    // request default e-mail client
                    Process.Start(mailto);
                }
                catch (Exception e) {
                    ShowExplorerError(null, Strings.DialogExplorerMailError, e);
                }
            }
            finally {
                // quit application upon return
                Environment.Exit(-1);
            }
        }