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)); } } }
/// <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); } } }