How can I make something that catches all 'unhandled' exceptions in a WinForms application?
Solution 1
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
.
Solution 2
In NET 4, certain exceptions are no longer caught by default; these tend to be exceptions that indicate a (possibly fatal) corrupted state of the executable, such as an AccessViolationException.
Try using the [HandleProcessCorruptedStateExceptions] tag in front of your main method, e.g.
using System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions
[HandleProcessCorruptedStateExceptions]
public static int Main()
{
try
{
// Catch any exceptions leaking out of the program
CallMainProgramLoop();
}
catch (Exception e) // We could be catching anything here
{
System.Console.WriteLine(e.Message);
return 1;
}
return 0;
}
Solution 3
A nice example can be found at http://www.csharp-examples.net/catching-unhandled-exceptions/ Basically, change your main to:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Application.Run(new Form1());
}
static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message, "Unhandled Thread Exception");
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show((e.ExceptionObject as Exception).Message, "Unhandled UI Exception");
}
Solution 4
You can use NBug library for that. With minimal setup like this:
NBug.Settings.Destination1 = "Type=Mail;[email protected];[email protected];SmtpServer=smtp.mycompany.com;";
AppDomain.CurrentDomain.UnhandledException += NBug.Handler.UnhandledException;
Application.ThreadException += NBug.Handler.ThreadException;
You can start collecting information on all unhandled bugs in your application, even when it's deployed to the clients. If you don't want to use a 3rd party library, you should attach to below events:
// These two should come before enabling visual styles or running the application
AppDomain.CurrentDomain.UnhandledException += ...
Application.ThreadException += ...
...
Application.Run(new Form1());
Comments
-
Isaac Bolinger over 2 years
Up until now, I just put a try/catch block around the
Application.Run
in theProgram.cs
entry point to the program. This catches all exceptions well enough in Debug mode, but when I run the program without the debug mode, exceptions don't get handled anymore. I get the unhandled exception box.I don't want this to happen. I want all exceptions to be caught when running in non-debug mode. The program has multiple threads and preferably all exceptions from them get caught by the same handler; I want to log exceptions in the DB. Does anyone have any advice in how to do this?
-
Teoman Soygul about 13 yearsYou're welcome. Use the NBug project discussion forum if you have further questions (nbusy.com/forum/f11) or use the [nbug] tag here.
-
neo2862 about 13 yearsOf course, you can also subscribe a "regular" event handler to the UnhandledException event. See msdn.microsoft.com/en-us/library/…
-
gideon about 13 yearsGuys on Win7 + VS10, if I subscribe to these events the subscription doesn't run, instead the regular Windows Vista/7 dialog shows up
Check Online for a Solution
OrClose the Program
.. etc. But if I do NOT subscribe, I get the regular generic .NET Unhandled Exception Window. This happens on Both Release and Debug builds, also tried settingApplication.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Doesn't change anything. -
Teoman Soygul about 13 years@giddy, after handling the exceptions you should exit the application with Environment.Exit(1); if you don't want the error window displayed.
-
gideon about 13 years@Teo thanks for your reply. I want my own error form to show up and then I want the app to exit. But the event subscription never runs, it just shows the generic Win Vista/7 dialog when it encounters exceptions. But if I don't subscribe the generic .NET unhandled exception dialog appears!
-
Teoman Soygul about 13 years@giddy Try hooking up to all possible unhandled exception events: UnhandledException, ThreadException (WinForms), DispatcherUnhandledException (WPF), UnobservedTaskException (Threading.Tasks). It is possible that you've missed one of these unhandled exception sources.
-
gideon about 13 yearsI'm on winforms, and subscribed to both Unhandled and Thread Exception.
-
Teoman Soygul about 13 yearsTry something like this one:
Application.ThreadException += (sender, e) => { new MyErrorForm(); Environment.Exit(0); };
note that I changed Environment.Exit(1); to Environment.Exit(0); which should prevent Vista/7 dialog. -
Isaac Bolinger about 13 yearsI made a background worker, and in the dowork event handler I intentially caused a null reference exception. However it didn't get caught by the AppDomain.CurrentDomain.UnhandledException in spite of setting these: Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
-
Can Gencer about 13 years@IsaacB, background worker catches exceptions itself. You can check the exception in the RunWorkerCompleted even, looking at the RunCompletedEventArgs.Error property.
-
Can Gencer about 13 yearsYou can test the exception handling for additional threads by putting this into the OnLoad of your main form. new Thread(() => { throw new Exception(); }).Start();
-
Nazar Grynko almost 11 yearsUnfortunately handling UnhandledException will not stop application from terminating :(
-
moltenform about 8 yearsInstead of the FriendlyName.EndsWith hack, try Debugger.IsAttached which is cleaner.
-
Kiquenet about 7 yearsCan I use
AppDomain.CurrentDomain.UnhandledException
andApplication.ThreadException
too with[HandleProcessCorruptedStateExceptions]
tag ? -
Kiquenet about 7 yearsGitHub is the new source repo. Send pull requests there: github.com/soygul/NBug
-
Kiquenet about 7 yearsI dont know the good patterns and practices. Be careful when using the AppDomain.UnhandledException event
Revision note:
I was pointed by Phillip Haack of this important omission.Other common source of mistakes is the Application.ThreadException event. There are lots of caveats when using them,
-
Kiquenet about 7 yearsIMHO, add notes in your answer, use
Debugger.IsAttached
for prevent catching the exceptions when debugging and handling UnhandledException will not stop application from terminating ( reference by @NazarGrynko) -
Kiquenet about 7 yearsCan I combine
AppDomain.CurrentDomain.UnhandledException and Application.ThreadException
with[HandleProcessCorruptedStateExceptions]
tag ? stackoverflow.com/a/5763158/206730 CLR Inside Out - Handling Corrupted State Exceptions certain exceptions are no longer caught by default; these tend to be exceptions that indicate a (possibly fatal) corrupted state of the executable, such as an AccessViolationException. -
Doug about 6 yearsIn order to not catch exceptions while debugging, you can check System.Diagnostics.Debugger.IsAttached property value. It's more elegant than checking the running executable name.
-
person27 almost 4 yearsThere's also usually the preprocessor variable DEBUG, for readers in the future.
-
Jesse Chisholm over 2 years@person27 re:
DEBUG
using that conditional protects you from running this in a DEBUG compile. The recommended techniques let you catch the otherwise unhandled exceptions regardless of DEBUG or RELEASE compile, but protect from trying to double catch them in your code AND in the debugger code.