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();
}
button1_Click
is fired.- thread get started and raises a
DividedByZeroException
. 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
Generics in C#, Using Type of a Variable as Parameter
System.Missingmethodexception: Method Not Found
How to Get the Full Path of Running Process
How to Get Windows Display Settings
Using Regex to Balance Match Parenthesis
Load an Exe File and Run It from Memory
How to Use Reflection to Inspect the Code in a Method
Easiest Way to Parse JSON Response
Create Folder and File on Current User Profile, from Admin Profile
How to Change the Table Names When Using ASP.NET Identity
How to Access Session Variables from Any Class in ASP.NET
Differences in String Compare Methods in C#
Calling Async Method Synchronously
Select N Random Elements from a List<T> in C#
C#: Difference Between ' += Anevent' and ' += New Eventhandler(Anevent)'