Unhandled exception handler in Prism apps

Topics: Prism v2 - WPF 3.5
Sep 30, 2009 at 9:37 PM

Hi,

I've got a Prism application that I'm starting to get ready to release to users.  One of the pieces of functionality I'd like is a last-chance exception handler to log any exceptions, along with their stack traces, that my team has managed to miss during development.  Normally I'd go and add an event handler for DispatcherUnhandledException in my App.xaml but this doesn't seem to be working.  My (admittedly trivial) test is simply to throw a new exception in the Shell project once it has finished loading.  This always results in the normal Debugger interaction rather that hitting my unhandled exception handler.  To double-check I've tried the same test running my project without the debugger attached.

I'm also noticing that I'm actually getting the Prism-supplied "ResolutionFailedException" rather than my generic Exception object.  I know Prism must have its own unhandled exception handler to be able to build up the additional exception information, so I'm trying to figure out how to plug into that.

Any help would be greatly appreciated.

Regards,

 

/jamief

Oct 7, 2009 at 5:25 PM

Hi,

Similar to jamief I'm in need of the correct way to implement a global exception handler.  Prior to converting the app to Composite WPF the global exception hander (using the Microsoft.Practices.EnterpriseLibrary.ExceptionHandling and Logging blocks )worked perfectly, with unhandled exceptions being caught in app.xaml.cs and the ExceptionPolicy.HandleException tossing the exception to the P&P assembly that, based on the config, both logged the exception to a file and displayed the exception to the user and kept the app alive.  Since converting the app to CompositeWPF the exception still gets logged and the error dialog gets momentarily displayed but then it whites out and the app crashes hard.  Is app.xaml.cs no longer the correct place to catch unhandled exceptions?  I initially thought it was some type of threading issue but added code to insure that the exception got handled on the dispatcher thread.

Below is the code that catches the exceptions and passes them on to the P&P Exception handling blocks.

Please provide some guidance.

Thanks,

Glenn

 

       private void ProcessUnhandledException(Exception ex)
        {
            // An unhandled exception occured somewhere in our application. Let
            //    // the 'Global Policy' handler have a try at handling it.
            try
            {
                bool rethrow = ExceptionPolicy.HandleException(ex, "Global Policy");
                if (rethrow)
                {
                    // Something has gone very wrong - exit the application.
                    Application.Current.Shutdown();
                }
            }
            catch (Exception ex2)
            {
                // Something has gone wrong during HandleException (e.g. incorrect configuration of the block).
                // Exit the application
                string errorMsg = "An unexpected exception occured while calling HandleException with policy 'Global Policy': " + Environment.NewLine + Environment.NewLine + ex2.Message;
                errorMsg += "Please check the event log for details about the exception." + Environment.NewLine + Environment.NewLine;

                QSMessageBox.Show(errorMsg, "Application Error", MessageBoxButton.OK, MessageBoxImage.Stop);

                Application.Current.Shutdown();
            }
            //Cursors = Cursors.Default;
        }

        private void Application_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            // some of the exceptions being thrown by the CAG appear to be coming from separate threads so we'll protect ourselves
            if (!Application.Current.Dispatcher.CheckAccess())
            {
                // Unhandled exceptions on worker threads will halt the application. We want to
                // use our global exception handler(s), so dispatch or "forward" to the UI thread.
                Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new ProcessUnhandledExceptionDelegate(this.ProcessUnhandledException), e.Exception);
            }
            else
            {
                this.ProcessUnhandledException(e.Exception);  // Already on UI thread; just rethrow the exception to global handlers
            }
            e.Handled = true;
        }

        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            // some of the exceptions being thrown by the CAG appear to be coming from separate threads so we'll protect ourselves
            if (!Application.Current.Dispatcher.CheckAccess())
            {
                // Unhandled exceptions on worker threads will halt the application. We want to
                // use our global exception handler(s), so dispatch or "forward" to the UI thread.
                Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new ProcessUnhandledExceptionDelegate(this.ProcessUnhandledException), (Exception)e.ExceptionObject);
            }
            else
            {
                this.ProcessUnhandledException((Exception)e.ExceptionObject);  // Already on UI thread; just rethrow the exception to global handlers
            }

            
        }

Oct 8, 2009 at 10:48 PM

Hi Jamie,

This thread provides more information about this subject (it is for Prism-v1 but the information is also valid for Prism-v2). As Prism does not provide specific guidance to handle exceptions, you might find the Exception Handling Application Block from the Enterprise Library useful.

Also, you should note that the Shell is created as part of the bootstrapping process, which may have its own exception handling mechanism (as opposed to throw an exception for example as a result of some user input).

Please let me know if this helps.

Damian Schenkelman
http://blogs.southworks.net/dschenkelman

 

Jul 26, 2011 at 3:25 AM

I would also be interested in some guidance on this. The link provided by Damian doesn't appear to work any more.

Is there any best practice guidance? For example, how best might this be implemented within the StockTrader Reference Implementation? Code samples, etc

Developer
Jul 26, 2011 at 12:58 PM

Hi,

The link provided by Damian can be found here. As for guidance about best practices about this, there isn't yet specific guidance about it in Prism.

I hope you find this helpful.

Guido Leandro Maliandi
http://blogs.southworks.net/gmaliandi