1

I want to set UnhandledExceptionMode.ThrowException for the current AppDomain and not only for the Application-Thread. An exception from another thread should be handled by my CurrentDomain_UnhandledException event handler, too. Is this possible? Here is my code:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        File.AppendAllText("Log.txt", ((Exception)e.ExceptionObject).Message + Environment.NewLine);
    }
}
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
PhazBlue
  • 79
  • 8
  • Do you want to catch [all exceptions](http://stackoverflow.com/a/21530177/1997232)? – Sinatr Oct 17 '14 at 11:16
  • 1
    Yes, i want to catch all unhandled exceptions in all threads and handle them in my event handler CurrentDomain_UnhandledException without .net framework's error prompt window popping up. – PhazBlue Oct 17 '14 at 11:38
  • I have updated my answer - the top section shows one way to achieve what you're looking for. The bottom section remains as it was. Without enabling the legacy exception policy, unhandled exceptions on any thread will terminate your application because they leave it in an unstable state. – Xharlie Oct 17 '14 at 11:53

1 Answers1

2

Perhaps you are looking for the behaviour provided by Application.ThreadException? http://msdn.microsoft.com/en-us/library/system.windows.forms.application.threadexception%28v=vs.80%29.aspx

One way to achieve the behaviour you want, according to your comment, is to enable the old unhandled exception policy from .Net 1.

In App.config:

<runtime>
    <legacyUnhandledExceptionPolicy enabled="1" />
</runtime>

Then modify your main method like this:

class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        try
        {
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

            ThreadPool.QueueUserWorkItem((object state) =>
            {
                throw new Exception("Exception thrown on Background Thread");
            });

            throw new Exception("Exception at the end of Main");
        }
        catch (Exception exception)
        {
            // Exceptions thrown on the Main Thread will pass through here
            HandleUnhandledException(exception);
        }
    }

    static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        // Exceptions thrown on Background Threads will pass through here
        HandleUnhandledException((Exception)e.ExceptionObject);
    }

    static void HandleUnhandledException(Exception exception)
    {
        // TODO: Write your Unhandled Exception routine here
        Console.WriteLine(exception.Message);
    }
}

Enabling the legacy exception policy causes exceptions on background threads to be ignored by the main thread. They will only ever be seen by the unhanded exception event listener. Exceptions on the main thread do need to be handled in order to prevent the .NET Unhandled Exception dialog but, by using a shared method, you can re-use the exception handling code.


The event handler that you attach to AppDomain.UnhandledException will catch all unhandled exceptions that originate on all the threads in the AppDomain. If you remove Windows-Forms from the picture, here is some code that illustrates it:

class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

        ThreadPool.QueueUserWorkItem((object state) =>
        {
            throw new Exception("Exception thrown on Background Thread");
        });

        throw new Exception("Exception at the end of Main");
    }

    static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        Console.WriteLine(((Exception)e.ExceptionObject).Message);
    }
}

If you run this, you will see that both exception messages are written to the console immediately before the application crashes due to the unhandled exception at the end of Main. (Note: this does illustrate that the event handler works for both exceptions but it has a race condition - in real life, an unhandled exception will kill the AppDomain before the next one could be raised)

Xharlie
  • 2,350
  • 3
  • 19
  • 39
  • Thank you! That was exactly what i wanted. You said that this is one way to do it. Is there a way which does not need a app.config? – PhazBlue Oct 17 '14 at 13:04
  • I don't think so. You could wrap all the thread-procs of all background threads in catch-all blocks and do the same for `Main` but, ultimately, if an exception were be go unhandled in a background thread, the new exception policy will end the application. When describing the new exception policy (from .NET 2.0) the MSDN says: "In most cases this means that the unhandled exception causes the application to terminate" before listing three exceptions: `Thread.Abort`, unloaded `AppDomain`, threads terminated by the runtime itself. http://msdn.microsoft.com/en-us/library/ms228965(v=vs.110).aspx – Xharlie Oct 17 '14 at 13:27