예제 #1
0
        internal static bool OnException(System.Exception e, bool isTerminating)
        {
            ExceptionReporting?.Invoke(e, EventArgs.Empty);
            var  proc    = Process.GetCurrentProcess();
            bool fromSTA = true;

            //avoid recursive reporting when IsTerminating is true, since we have registered both Main Form and AppDomain with unhandled exceptions
            if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
            {
                if (_previousException != null && e != null && _previousException.ToString() == e.ToString())
                {
                    ReportLogger.LogInfo(new ArgumentException("Trying to report on the same exception.", e).ToString());
                    //same as previous
                    return(_tryContinueAfterException);
                }

                _previousException = e;
            }

            ReportLogger.LogInfo("Received exception  (isTerminating = " + isTerminating + ")");

            TheException = e;

            try
            {
                //use ExceptionRegistrator.UseReportGUI to control if UI is to be used or not.
                if (!useReportGUI)
                {
                    ReportExceptionWithNoGUI(Reporter, Version, ApplicationName, e);
                    return(false);
                }
                // XAML issue with MTA threads.
                if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
                {
                    LogToFile(e);
                    ReportInSTA(e, isTerminating);
                    fromSTA = false;
                    return(_tryContinueAfterException);
                }

                //only report one exception at the time.
                lock (_syncObject)
                {
                    string errorText = CreateExceptionText(e);

                    //show the error to the user and collect a description of the error from the user.
                    try
                    {
                        //show the exception using the registered IReportForm.
                        //if return value is false -> cancel
                        if (!_form.ShowException(errorText,
                                                 //this callback is to be used when the form click on the Send button.
                                                 DoPost))
                        {
                            //cancel report exception to log
                            LogToFile(e);
                        }
                    }
                    catch (System.Exception ex)
                    {
                        //log report exception
                        var report = new TFSExceptionReport(ApplicationName, Reporter, Reporter, e, Version,
                                                            "THIS IS A AUTO GENERATED TEXT: Failed to show exception report.");

                        ReportLogger.LogToFile(report);

                        ReportLogger.LogExceptionsDuringDelivery(
                            new InvalidOperationException("Failed to show exception report.", ex));
                    }
                }
            }
            catch (ThreadAbortException terminate)
            {
                try
                {
                    _form.Window.Close();
                }
                catch
                {
                    //ignore...
                }
                ReportLogger.LogInfo(new ThreadStateException("Report form is terminating.", terminate).ToString());
            }
            finally
            {
                //we should inform the user that the application is about to terminate.
                // currently only support for WPF.
                if (_showExitAppWindow && isTerminating && fromSTA && Application.Current != null)
                {
                    try
                    {
                        var terminateWindow = new IsTerminatingWindow();
                        terminateWindow.Topmost = true;
                        terminateWindow.Show();

                        //sleep for 5000 seconds.
                        Thread.Sleep(5000);

                        terminateWindow.Close();
                    }
                    catch
                    {
                        //for now ignore ... this will happen if thread is MTA...but no more time to code.
                    }
                }
            }

            return(_tryContinueAfterException);
        }