none
MessageBox closes immediately in DispatcherUnhandledException handler

    Question

  • Hi,

    I have a DispatcherUnhandledException handler in Application.xaml.vb which should simply display an error message to the user, and after the user presses OK, shutdown the application.  Code:

        Private Sub GeneralExceptionHandler(ByVal sender As Object, ByVal e As DispatcherUnhandledExceptionEventArgs)
    
            ClosingAfterException = True
    
            MessageBox.Show("Exception: " + e.Exception.Message, "Fatal Error", MessageBoxButton.OK)
    
            MyBase.Shutdown()
    
            e.Handled = True
    
        End Sub
    The message box does display, but only for a fraction of a second.  It doesn't wait for the user to press OK.  I tried a sample from MSDN which does something like this and the message box does stick around for the user to click on the button.  Any idea as to what could be causing this behavior?

    Thanks,
    Michel
    Wednesday, June 17, 2009 3:36 PM

Answers

  • Hi, Michel!

    WPF has an interesting bug (or "feature" as you want it):
    YOU CAN`T SHOW ANY MESSAGE BOXES UNTIL YOU OPEN AT LEAST ONE WPF WINDOW.

    As a workaround we need to open one hidden window at the beginning of application startup. And if our application starts successfully, than we close this "helper" window.

    Something like this:

    using System;
    using System.Windows;
    using System.Windows.Threading;
    
    namespace WpfStartup
    {
        public partial class App : Application
        {
            bool IsStartingUp;
    
            public App()
                : base()
            {
                ShutdownMode = ShutdownMode.OnExplicitShutdown;
                IsStartingUp = true;
            }
    
            protected override void OnExit(ExitEventArgs e)
            {
                DispatcherUnhandledException -=
                    new DispatcherUnhandledExceptionEventHandler(
                        DispatcherUnhandledExceptionHandler);
                base.OnExit(e);
            }
    
            protected override void OnStartup(StartupEventArgs e)
            {
                DispatcherUnhandledException +=
                    new DispatcherUnhandledExceptionEventHandler(
                        DispatcherUnhandledExceptionHandler);
    
                // WPF Bug Workaround: while we have no WPF window open we can`t show MessageBox.
                Window WpfBugWindow = new Window()
                {
                    AllowsTransparency = true,
                    Background = System.Windows.Media.Brushes.Transparent,
                    WindowStyle = WindowStyle.None,
                    Top = 0,
                    Left = 0,
                    Width = 1,
                    Height = 1,
                    ShowInTaskbar = false
                };
    
                WpfBugWindow.Show();
    
                try
                {
                    base.OnStartup(e);
                    
                    // If some problem occursduring the startup, than we have an exception here.
                    InitializeMyApplication();
    
                    // And if there no any problem, than we continue...
                    IsStartingUp = false;
                    ShutdownMode = ShutdownMode.OnLastWindowClose;
                    WpfBugWindow.Close();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Can`t launch application because of:\r\n" + ex.ToString(),
                        "My Application", MessageBoxButton.OK, MessageBoxImage.Error);
                    WpfBugWindow.Close();
                    Shutdown(1);
                }
            }
    
            void InitializeMyApplication()
            {
                // Let`s imagine that we have some exception during the application startup.
                // For example:
                throw new InvalidOperationException("Big problem occurs...");
            }
    
            void DispatcherUnhandledExceptionHandler(object sender,
                DispatcherUnhandledExceptionEventArgs e)
            {
                if (!e.Handled)
                {
                    e.Handled = true;
                    if (!IsStartingUp)
                        MessageBox.Show(e.Exception.ToString(), "Error",
                            MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }
    }
    



    Hope, this helps.
    • Proposed as answer by Alexander Yudakov Wednesday, June 24, 2009 9:10 PM
    • Marked as answer by Michel R Thursday, June 25, 2009 11:33 AM
    Wednesday, June 24, 2009 9:10 PM

All replies

  • Hi Michel,

    Which exception error do you get? And where do you use the ClosingAfterException variable?

    Best Regards,
    Zhi-Xin


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Send us any feedback you have about the help from MSFT at fbmsdn@microsoft.com.
    Wednesday, June 24, 2009 10:42 AM
  • I don't recall the exact exception, but it was when trying to open a web service (WCF) connection when the web service was not available (in this case, because I hadn't started my development server - frequent problem early in the morning. :))  I also tried just throwing generic exceptions, with the same result.

    Two things I later noticed:

    1) If I add a second message box (after the one that closed), the second one remains on screen until I click OK

    2) I was actually getting a second exception raised just after the first one, even before it reached the handler.  I think this was because WPF was still working on setting up its bindings (some of them dependent on data retrieved from the web service), and somehow that second got triggered right away.  Took me a while to figure out this was (probably) the cause here.  I thought the second exception was the reason for the message box disappearing, but it was raised before it ever got there (if I recall correctly, and if it's not just the debugger that got confused.)

    "ClosingAfterException" is just something I use in the Closing event of the window to prevent some things from happening when the application is closed because of an exception.  I had the disappearing MessageBox problem before I put that in there, so as far as I can tell, it's unrelated.

    Eventually I ended up grabbing a custom WPFMessageBox which is basically just a window that you display using the same parameter as the standard message box.  This one stays on the screen, waiting for the user to click OK.  Odd...  I don't like workarounds, but I had more pressing things to work on. :\  But hey, it's prettier than the standard message box. :)

    To resolve (2) above, I now check that the web service is available early at application startup (although I still do check (and raise the exception if necessary) every time I attempt to open it during the lifetime of the application.)  Chances are that it in the few seconds required to get the main window up and running after the initial check, it won't go down.

    A bit fuzzy on some details, but overall that's it.

    Thanks!
    Michel
    Wednesday, June 24, 2009 5:41 PM
  • Hi, Michel!

    WPF has an interesting bug (or "feature" as you want it):
    YOU CAN`T SHOW ANY MESSAGE BOXES UNTIL YOU OPEN AT LEAST ONE WPF WINDOW.

    As a workaround we need to open one hidden window at the beginning of application startup. And if our application starts successfully, than we close this "helper" window.

    Something like this:

    using System;
    using System.Windows;
    using System.Windows.Threading;
    
    namespace WpfStartup
    {
        public partial class App : Application
        {
            bool IsStartingUp;
    
            public App()
                : base()
            {
                ShutdownMode = ShutdownMode.OnExplicitShutdown;
                IsStartingUp = true;
            }
    
            protected override void OnExit(ExitEventArgs e)
            {
                DispatcherUnhandledException -=
                    new DispatcherUnhandledExceptionEventHandler(
                        DispatcherUnhandledExceptionHandler);
                base.OnExit(e);
            }
    
            protected override void OnStartup(StartupEventArgs e)
            {
                DispatcherUnhandledException +=
                    new DispatcherUnhandledExceptionEventHandler(
                        DispatcherUnhandledExceptionHandler);
    
                // WPF Bug Workaround: while we have no WPF window open we can`t show MessageBox.
                Window WpfBugWindow = new Window()
                {
                    AllowsTransparency = true,
                    Background = System.Windows.Media.Brushes.Transparent,
                    WindowStyle = WindowStyle.None,
                    Top = 0,
                    Left = 0,
                    Width = 1,
                    Height = 1,
                    ShowInTaskbar = false
                };
    
                WpfBugWindow.Show();
    
                try
                {
                    base.OnStartup(e);
                    
                    // If some problem occursduring the startup, than we have an exception here.
                    InitializeMyApplication();
    
                    // And if there no any problem, than we continue...
                    IsStartingUp = false;
                    ShutdownMode = ShutdownMode.OnLastWindowClose;
                    WpfBugWindow.Close();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Can`t launch application because of:\r\n" + ex.ToString(),
                        "My Application", MessageBoxButton.OK, MessageBoxImage.Error);
                    WpfBugWindow.Close();
                    Shutdown(1);
                }
            }
    
            void InitializeMyApplication()
            {
                // Let`s imagine that we have some exception during the application startup.
                // For example:
                throw new InvalidOperationException("Big problem occurs...");
            }
    
            void DispatcherUnhandledExceptionHandler(object sender,
                DispatcherUnhandledExceptionEventArgs e)
            {
                if (!e.Handled)
                {
                    e.Handled = true;
                    if (!IsStartingUp)
                        MessageBox.Show(e.Exception.ToString(), "Error",
                            MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }
    }
    



    Hope, this helps.
    • Proposed as answer by Alexander Yudakov Wednesday, June 24, 2009 9:10 PM
    • Marked as answer by Michel R Thursday, June 25, 2009 11:33 AM
    Wednesday, June 24, 2009 9:10 PM
  • Hi Alexander,

    Interesting - and a bit maddening! :)  That will take care of things, thanks!

    Michel
    Thursday, June 25, 2009 11:34 AM
  • Notice: This issue takes place only if you use SplashScreen as it designed in WPF 3.5 SP1

    Sunday, August 30, 2009 4:01 PM
  • Interesting.- a bit messy but useful

    Moattar

    Tuesday, February 28, 2012 11:17 AM
  • I agree, messy but helpful. Thanks for the tip!
    Tuesday, July 03, 2012 11:19 PM