how to catch an unhandled exception in c#?

14,317

Solution 1

Catching all exceptions from main UI thread worked for me:

static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            // Add handler for UI thread exceptions
            Application.ThreadException += new ThreadExceptionEventHandler(UIThreadException);

            // Force all WinForms errors to go through handler
            Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

            // This handler is for catching non-UI thread exceptions
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

            Application.Run(new Form1());
        }

        private static void CurrentDomain_UnhandledException(Object sender, UnhandledExceptionEventArgs e)
        {
            try
            {
                Exception ex = (Exception)e.ExceptionObject;
                MessageBox.Show("Unhadled domain exception:\n\n" + ex.Message);
            }
            catch (Exception exc)
            {
                try
                {
                    MessageBox.Show("Fatal exception happend inside UnhadledExceptionHandler: \n\n"
                        + exc.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                }
                finally
                {
                    Application.Exit();
                }
            }

            // It should terminate our main thread so Application.Exit() is unnecessary here
        }

        private static void UIThreadException(object sender, ThreadExceptionEventArgs t)
        {
            try
            {
                MessageBox.Show("Unhandled exception catched.\n Application is going to close now.");
            }
            catch
            {
                try
                {
                    MessageBox.Show("Fatal exception happend inside UIThreadException handler",
                        "Fatal Windows Forms Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Stop);
                }
                finally
                {
                    Application.Exit();
                }
            }

            // Here we can decide if we want to end our application or do something else
            Application.Exit();
        }
    }

Solution 2

You Don't have to use Application.Exit or Environment.Exit, this is just the behavior of visual studio that it keeps on intercepting causing line of unhandled exceptions but in reality your application is going to crash (exit) if isTerminating flag is set, And this is the right use of it, i would recommend not to use any userinterface for this nor any other resource hungry process in this event just silent log would do.

the purpose of this event is get the log why it exactly happened, this is not a point to make your application look good while its crashing, or apologizing user on this. but you will have chance to do above when user logs in next time.

Therefore even if you are planning to email the exception log, best way is to write the file and on next start up of application email the file.

I usually use log4net and use these events as follow.

[STAThread]
static void Main()
{
    log.Info("Starting deployer application");

    Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
    AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
    Application.ApplicationExit += new EventHandler(Application_ApplicationExit);

    Application.Run(ConnectionForm.GetInstance);
}

static void Application_ApplicationExit(object sender, EventArgs e)
{
    log.Info("Application Closed");
}

static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    log.Error(string.Format("*** UNHANDLED APPDOMAIN EXCEPTION ({0}) *****", e.IsTerminating ? "Terminating" : "Non-Terminating"), e.ExceptionObject as Exception);
}

static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
    log.Error("*** UNHANDLED THREAD EXCEPTION *****", e.Exception);
}

If you never used log4net before this can be helpful.

Share:
14,317
user1327073
Author by

user1327073

Updated on June 11, 2022

Comments

  • user1327073
    user1327073 almost 2 years

    I'm trying to catch any unhandeled Exception in my program, i use this code in the Program main class

    static class Program
    {
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    
    AppDomain.CurrentDomain.UnhandledException += new    UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
    
    Application.Run(new Form1());
    }
    
    
    public static void CurrentDomain_UnhandledException(Object sender,  UnhandledExceptionEventArgs e)
    {
    
    MessageBox.Show((e.ExceptionObject as Exception).Message, "Unhandled domain Exception");
    Application.Exit();
    }
    

    now im my form form1, i try to create a simple exception : divide by zero, without a try catch block, the code in the main module intercepts the exception indeed, but i still have the MS Visual studio dialog. the application doesn't exit. of course in real situations, i willl log/mail the error. but i would like to understand why the execution continues after i intercept my exception ? thanks