예제 #1
0
        public static ErrorResult?ShowFallbackProblemDialog(string levelOfProblem, Exception exception, string detailedMessage, string shortUserLevelMessage, bool isShortMessagePreEncoded = false,
                                                            string notifySecondaryButtonLabel = null, ErrorResult?notifySecondaryPressedResult = null)
        {
            var fallbackReporter = new WinFormsErrorReporter();

            if (shortUserLevelMessage == null)
            {
                shortUserLevelMessage = "";
            }

            string decodedShortUserLevelMessage = isShortMessagePreEncoded ? XmlString.FromXml(shortUserLevelMessage).Unencoded : shortUserLevelMessage;
            string message = decodedShortUserLevelMessage;

            if (!String.IsNullOrEmpty(detailedMessage))
            {
                message += $"\n{detailedMessage}";
            }

            if (levelOfProblem == ProblemLevel.kFatal)
            {
                if (exception != null)
                {
                    fallbackReporter.ReportFatalException(exception);
                }
                else
                {
                    fallbackReporter.ReportFatalMessageWithStackTrace(message, null);
                }

                return(null);
            }
            else if (levelOfProblem == ProblemLevel.kNonFatal || levelOfProblem == ProblemLevel.kUser)
            {
                // FYI, if levelOfProblem==kUser, we're unfortunately going to be
                // using the messaging from NonFatal even though we would ideally like to have the customized messaging for levelOfProblem==kUser,
                // but we'll just live with it because there's no easy way to customize it. It's probably an extremely rare situation anyway
                if (String.IsNullOrEmpty(message))
                {
                    fallbackReporter.ReportNonFatalException(exception, new ShowAlwaysPolicy());
                }
                else
                {
                    fallbackReporter.ReportNonFatalExceptionWithMessage(exception, message);
                }

                return(null);
            }
            else             // Presumably, levelOfProblem = "notify" now
            {
                if (String.IsNullOrEmpty(notifySecondaryButtonLabel) || notifySecondaryPressedResult == null)
                {
                    return(fallbackReporter.NotifyUserOfProblem(new ShowAlwaysPolicy(), null, ErrorResult.OK,
                                                                message));
                }
                else
                {
                    return(fallbackReporter.NotifyUserOfProblem(new ShowAlwaysPolicy(), notifySecondaryButtonLabel, notifySecondaryPressedResult ?? ErrorResult.OK, message));
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Notifies the user of a problem, using a browser-based dialog.
        /// Note: This is designed to be called by LibPalaso's ErrorReport class.
        /// </summary>
        /// <param name="policy">Checks if we should notify the user, based on the contents of {message}</param>
        /// <param name="alternateButton1Label">The text that goes on the Report button. However, if speicfied, this.ReportButtonLabel takes precedence over this parameter</param>
        /// <param name="resultIfAlternateButtonPressed">This is the value that this method should return so that the caller (mainly LibPalaso ErrorReport)
        /// can know if the alternate button was pressed, and if so, invoke whatever actions are desired.</param>
        /// <param name="message">The message to show to the user</param>
        /// <returns>If closed normally, returns ErrorResult.OK
        /// If the report button was pressed, returns {resultIfAlternateButtonPressed}.
        /// If the secondary action button was pressed, returns {this.SecondaryActionResult} if that is non-null; otherwise falls back to {resultIfAlternateButtonPressed}
        /// If an exception is throw while executing this function, returns ErrorResult.Abort.
        /// </returns>
        public ErrorResult NotifyUserOfProblem(IRepeatNoticePolicy policy, string alternateButton1Label, ErrorResult resultIfAlternateButtonPressed, string message)
        {
            // Let this thread try to acquire the lock, if necessary
            // Note: It is expected that sometimes this function will need to acquire the lock for this thread,
            //       and sometimes it'll already be acquired.
            //       The reason is because for legacy code that calls ErrorReport directly, this function is the first entry point into this class.
            //       But for code that needs the new secondaryAction functionality, it needs to enter through CustomNotifyUser*().
            //       That function wants to acquire a lock so that the instance variables it sets aren't modified by any other thread before
            //       entering this NotifyUserOfProblem() function.
            bool wasAlreadyLocked = System.Threading.Monitor.IsEntered(_lock);

            if (!wasAlreadyLocked)
            {
                System.Threading.Monitor.Enter(_lock);
            }

            try
            {
                ErrorResult result = ErrorResult.OK;
                if (policy.ShouldShowMessage(message))
                {
                    ErrorReport.OnShowDetails = null;
                    var reportButtonLabel = GetReportButtonLabel(alternateButton1Label);
                    result = ShowNotifyDialog(ProblemLevel.kNotify, message, null, reportButtonLabel, resultIfAlternateButtonPressed, this.SecondaryActionButtonLabel, this.SecondaryActionResult);
                }

                ResetToDefaults();

                return(result);
            }
            catch (Exception e)
            {
                var fallbackReporter = new WinFormsErrorReporter();
                fallbackReporter.ReportNonFatalException(e, new ShowAlwaysPolicy());

                return(ErrorResult.Abort);
            }
            finally
            {
                // NOTE: Each thread needs to make sure it calls Exit() the same number of times as it calls Enter()
                // in order for other threads to be able to acquire the lock later.
                if (!wasAlreadyLocked)
                {
                    System.Threading.Monitor.Exit(_lock);
                }
            }
        }