How to Make Something That Catches All 'Unhandled' Exceptions in a Winforms Application

How can I make something that catches all 'unhandled' exceptions in a WinForms application?

Take a look at the example from the ThreadException documentation:

public static void Main(string[] args)
{
// Add the event handler for handling UI thread exceptions to the event.
Application.ThreadException += new
ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);

// Set the unhandled exception mode to force all Windows Forms errors
// to go through our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

// Add the event handler for handling non-UI thread exceptions to the event.
AppDomain.CurrentDomain.UnhandledException += new
UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
}

You might also want to not catch exceptions when debugging, as this makes it easier to debug. It is somewhat of a hack, but for that you can wrap the above code around with

 if (!AppDomain.CurrentDomain.FriendlyName.EndsWith("vshost.exe")) { ... }

To prevent catching the exceptions when debugging.

EDIT: An alternate way to check for your application running inside a debugger that feels cleaner than checking a filename.

(see comments by moltenform, Kiquenet and Doug)

if(!System.Diagnostics.Debugger.IsAttached) { ... }

This avoids the problem of using a different debugger than vshost.exe.

Catch Application Exceptions in a Windows Forms Application

In Windows Forms applications, when an exception is thrown anywhere in the application (on the main thread or during asynchronous calls), you can catch it by registering for the ThreadException event on the Application. In this way you can treat all the exceptions in the same way.

Application.ThreadException += new ThreadExceptionEventHandler(MyCommonExceptionHandlingMethod);

private static void MyCommonExceptionHandlingMethod(object sender, ThreadExceptionEventArgs t)
{
//Exception handling...
}

C# Winforms handle unhandled exceptions

You need to change Application UnhandledExceptionMode
to UnhandledExceptionMode.CatchException to make things works correctly. Microsoft already wrote a very good article about it here.

I tried to simulate your work. Everything worked well, take a look on my example.

    [STAThread]
static void Main()
{
// Set the unhandled exception mode to force all Windows Forms errors to go through
// our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

// Add the event handler for handling UI thread exceptions to the event.
Application.ThreadException += Application_ThreadException;

// Add the event handler for handling non-UI thread exceptions to the event.
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}

private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message, "Application_ThreadException");
Application.Exit();
}

private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var exception = e.ExceptionObject as Exception;
MessageBox.Show(exception.Message, "CurrentDomain_UnhandledException");
Application.Exit();
}

So, if we raise an exception inside a thread like below:

    private void button1_Click(object sender, EventArgs e)
{
var thread = new Thread(delegate () {
throw new DivideByZeroException();
});

thread.Start();
}
  1. button1_Click is fired.
  2. thread get started and raises a DividedByZeroException.
  3. CurrentDomain_UnhandledException catches the exception, shows the message and closes the app

Is it possible to have one Exception handler for multiple timers in a C# class?

If your timer is a System.Timers.Timer the reason is documented by MSDN here:

The Timer component catches and suppresses all exceptions thrown by event handlers for the Elapsed event.

Take a look at this similar question:
How do I get the Exception that happens in Timer Elapsed event?

You'll have to catch the exceptions that are thrown in the elapsed handler, and rethrow them on a ThreadPool thread.

Using your code above and extending the answer from the referenced question:

private void ChangeFilesTimer_Tick(object sender, EventArgs e)
{
try
{
RunChangeFiles();
}
catch (Exception ex)
{
ThreadPool.QueueUserWorkItem(
_ => { throw new Exception("Exception on timer thread.", ex); });
}
}

If your timer is a System.Windows.Forms.Timer then you will need to hook into the Application.ThreadException event to handle unhandled exceptions.

Subscribe to this event prior to calling Application.Run().


You can also handle logging of the Exception in a local exception handling block before rethrowing the exception.

try
{
/// ...
}
catch (Exception ex)
{
if (ex is ArgumentException)
{
/// handle known or specific exceptions here
}
else
{
/// log then rethrow unhandled exceptions here
logExceptions(ex);
throw;
}
}

Handling Unhandled Exceptions from Winforms components in WPF

Have you tried System.Windows.Forms.Application.ThreadException and System.Windows.Forms.Application.SetUnhandledExceptionMode ?

Unable to capture Unhandled Exceptions in Winforms

Try disabling exception catching in VS, as it seems to catch the exception before it gets to your handlers.

Debug > Exceptions... > Uncheck User-unhandled for Common Language Runtime Exceptions.



Related Topics



Leave a reply



Submit