Handling unhandled exceptions problem - c#

I wanted to set some handler for all the unexpected exceptions that I might not have caught inside my code. In Program.Main() I used the following code:
AppDomain.CurrentDomain.UnhandledException
+= new UnhandledExceptionEventHandler(ErrorHandler.HandleException);
But it didn't work as I expected. When I started the application in debugging mode and threw an exception it did call the handler, but afterwards the exception helper in Visual Studio popped up as if the exception occurred without any handling. I tried Application.Exit() inside the handler but it didn't work as well.
What I would like to achieve is that the exception is handled with my handler and then the application closes nicely. Is there any other way to do it or am I using the code above in the wrong way?

Normally I use something like this to try and catch all unexpected top-level exceptions.
using System;
static class Program
{
[STAThread]
static void Main(string[] argv)
{
try
{
AppDomain.CurrentDomain.UnhandledException += (sender,e)
=> FatalExceptionObject(e.ExceptionObject);
Application.ThreadException += (sender,e)
=> FatalExceptionHandler.Handle(e.Exception);
// whatever you need/want here
Application.Run(new MainWindow());
}
catch (Exception huh)
{
FatalExceptionHandler.Handle(huh);
}
}
static void FatalExceptionObject(object exceptionObject) {
var huh = exceptionObject as Exception;
if (huh == null) {
huh = new NotSupportedException(
"Unhandled exception doesn't derive from System.Exception: "
+ exceptionObject.ToString()
);
}
FatalExceptionHandler.Handle(huh);
}
}
Maybe it is something you find helpful too? This main code routes all three ways of catching unexpected top-level exceptions through one method call. All you now need is a static class FatalExceptionHandler that includes your top-level exception handling in its Handle method.
And really, any application developer knows there are really just two things to do there:
Show/log the exception like you see fit
Make sure you exit/kill the application process
If you think item two is strange, remember that we only bother to do this in the first place for really exceptional situations. These things are probably bugs that need changes to your application to be accurately addressed. Any other exception handling - the functional kind - should be lower down inside your actual program code, catching specific kinds of exceptions where this makes sense and handling them there in the way that makes sense. Anything else should bubble up to your FatalExceptionHandler to make itself known and stop the possibly crippled program from working from corrupted state
Dead programs tell no lies... ;-)

It's because you're running it through Visual Studio in Debug mode. If you release and install your app somewhere else, nothing but your global exception handler will be processed.

Note that unhandled exceptions are still pretty fatal; you can only really use this for logging, or maybe some hasty close-down. Neither this nor Application.ThreadException can be used as a global sink for errors.
The better approach is to add proper handling - for example, around your entire Main() logic. Note that even this can't catch a few exceptions, such as errors during form-load (which get particularly nasty - you can catch them with a debugger attached, but not without).

Perhaps what you're looking for is Environment.Exit(int errorcode)

That behavior is by design.
But there is a work-around.
Either you call Process.GetCurrentProcess().Kill(); within the handler, or simply do not let the handler end.
Check out the example:
class Program
{
void Run()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Console.WriteLine("Press enter to exit.");
do
{
(new Thread(delegate()
{
throw new ArgumentException("ha-ha");
})).Start();
} while (Console.ReadLine().Trim().ToLowerInvariant() == "x");
Console.WriteLine("last good-bye");
}
int r = 0;
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Interlocked.Increment(ref r);
Console.WriteLine("handled. {0}", r);
Console.WriteLine("Terminating " + e.IsTerminating.ToString());
Thread.CurrentThread.IsBackground = true;
Thread.CurrentThread.Name = "Dead thread";
while (true)
Thread.Sleep(TimeSpan.FromHours(1));
//Process.GetCurrentProcess().Kill();
}
static void Main(string[] args)
{
Console.WriteLine("...");
(new Program()).Run();
}
}
This should not be a default sink for exceptions, surely.
But this should be done to report exceptions gracefully.

Note: if you're application is a Windows Forms application, don't forget to:
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
... or else the application will terminate, even if you handle the exceptions with the handlers specified by the other answers.

Related

Is there a way to show an MessageBox on any exception? [duplicate]

Up until now, I just put a try/catch block around the Application.Run in the Program.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?
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.
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;
}
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");
}
You can use NBug library for that. With minimal setup like this:
NBug.Settings.Destination1 = "Type=Mail;From=me#mycompany.com;To=bugtracker#mycompany.com;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());

Should UnhandledException notify all unhandled exceptions? [duplicate]

I wanted to set some handler for all the unexpected exceptions that I might not have caught inside my code. In Program.Main() I used the following code:
AppDomain.CurrentDomain.UnhandledException
+= new UnhandledExceptionEventHandler(ErrorHandler.HandleException);
But it didn't work as I expected. When I started the application in debugging mode and threw an exception it did call the handler, but afterwards the exception helper in Visual Studio popped up as if the exception occurred without any handling. I tried Application.Exit() inside the handler but it didn't work as well.
What I would like to achieve is that the exception is handled with my handler and then the application closes nicely. Is there any other way to do it or am I using the code above in the wrong way?
Normally I use something like this to try and catch all unexpected top-level exceptions.
using System;
static class Program
{
[STAThread]
static void Main(string[] argv)
{
try
{
AppDomain.CurrentDomain.UnhandledException += (sender,e)
=> FatalExceptionObject(e.ExceptionObject);
Application.ThreadException += (sender,e)
=> FatalExceptionHandler.Handle(e.Exception);
// whatever you need/want here
Application.Run(new MainWindow());
}
catch (Exception huh)
{
FatalExceptionHandler.Handle(huh);
}
}
static void FatalExceptionObject(object exceptionObject) {
var huh = exceptionObject as Exception;
if (huh == null) {
huh = new NotSupportedException(
"Unhandled exception doesn't derive from System.Exception: "
+ exceptionObject.ToString()
);
}
FatalExceptionHandler.Handle(huh);
}
}
Maybe it is something you find helpful too? This main code routes all three ways of catching unexpected top-level exceptions through one method call. All you now need is a static class FatalExceptionHandler that includes your top-level exception handling in its Handle method.
And really, any application developer knows there are really just two things to do there:
Show/log the exception like you see fit
Make sure you exit/kill the application process
If you think item two is strange, remember that we only bother to do this in the first place for really exceptional situations. These things are probably bugs that need changes to your application to be accurately addressed. Any other exception handling - the functional kind - should be lower down inside your actual program code, catching specific kinds of exceptions where this makes sense and handling them there in the way that makes sense. Anything else should bubble up to your FatalExceptionHandler to make itself known and stop the possibly crippled program from working from corrupted state
Dead programs tell no lies... ;-)
It's because you're running it through Visual Studio in Debug mode. If you release and install your app somewhere else, nothing but your global exception handler will be processed.
Note that unhandled exceptions are still pretty fatal; you can only really use this for logging, or maybe some hasty close-down. Neither this nor Application.ThreadException can be used as a global sink for errors.
The better approach is to add proper handling - for example, around your entire Main() logic. Note that even this can't catch a few exceptions, such as errors during form-load (which get particularly nasty - you can catch them with a debugger attached, but not without).
Perhaps what you're looking for is Environment.Exit(int errorcode)
That behavior is by design.
But there is a work-around.
Either you call Process.GetCurrentProcess().Kill(); within the handler, or simply do not let the handler end.
Check out the example:
class Program
{
void Run()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Console.WriteLine("Press enter to exit.");
do
{
(new Thread(delegate()
{
throw new ArgumentException("ha-ha");
})).Start();
} while (Console.ReadLine().Trim().ToLowerInvariant() == "x");
Console.WriteLine("last good-bye");
}
int r = 0;
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Interlocked.Increment(ref r);
Console.WriteLine("handled. {0}", r);
Console.WriteLine("Terminating " + e.IsTerminating.ToString());
Thread.CurrentThread.IsBackground = true;
Thread.CurrentThread.Name = "Dead thread";
while (true)
Thread.Sleep(TimeSpan.FromHours(1));
//Process.GetCurrentProcess().Kill();
}
static void Main(string[] args)
{
Console.WriteLine("...");
(new Program()).Run();
}
}
This should not be a default sink for exceptions, surely.
But this should be done to report exceptions gracefully.
Note: if you're application is a Windows Forms application, don't forget to:
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
... or else the application will terminate, even if you handle the exceptions with the handlers specified by the other answers.

Why the `AppDomain.UnhandledException` event doesn't happen in my case? [duplicate]

I wanted to set some handler for all the unexpected exceptions that I might not have caught inside my code. In Program.Main() I used the following code:
AppDomain.CurrentDomain.UnhandledException
+= new UnhandledExceptionEventHandler(ErrorHandler.HandleException);
But it didn't work as I expected. When I started the application in debugging mode and threw an exception it did call the handler, but afterwards the exception helper in Visual Studio popped up as if the exception occurred without any handling. I tried Application.Exit() inside the handler but it didn't work as well.
What I would like to achieve is that the exception is handled with my handler and then the application closes nicely. Is there any other way to do it or am I using the code above in the wrong way?
Normally I use something like this to try and catch all unexpected top-level exceptions.
using System;
static class Program
{
[STAThread]
static void Main(string[] argv)
{
try
{
AppDomain.CurrentDomain.UnhandledException += (sender,e)
=> FatalExceptionObject(e.ExceptionObject);
Application.ThreadException += (sender,e)
=> FatalExceptionHandler.Handle(e.Exception);
// whatever you need/want here
Application.Run(new MainWindow());
}
catch (Exception huh)
{
FatalExceptionHandler.Handle(huh);
}
}
static void FatalExceptionObject(object exceptionObject) {
var huh = exceptionObject as Exception;
if (huh == null) {
huh = new NotSupportedException(
"Unhandled exception doesn't derive from System.Exception: "
+ exceptionObject.ToString()
);
}
FatalExceptionHandler.Handle(huh);
}
}
Maybe it is something you find helpful too? This main code routes all three ways of catching unexpected top-level exceptions through one method call. All you now need is a static class FatalExceptionHandler that includes your top-level exception handling in its Handle method.
And really, any application developer knows there are really just two things to do there:
Show/log the exception like you see fit
Make sure you exit/kill the application process
If you think item two is strange, remember that we only bother to do this in the first place for really exceptional situations. These things are probably bugs that need changes to your application to be accurately addressed. Any other exception handling - the functional kind - should be lower down inside your actual program code, catching specific kinds of exceptions where this makes sense and handling them there in the way that makes sense. Anything else should bubble up to your FatalExceptionHandler to make itself known and stop the possibly crippled program from working from corrupted state
Dead programs tell no lies... ;-)
It's because you're running it through Visual Studio in Debug mode. If you release and install your app somewhere else, nothing but your global exception handler will be processed.
Note that unhandled exceptions are still pretty fatal; you can only really use this for logging, or maybe some hasty close-down. Neither this nor Application.ThreadException can be used as a global sink for errors.
The better approach is to add proper handling - for example, around your entire Main() logic. Note that even this can't catch a few exceptions, such as errors during form-load (which get particularly nasty - you can catch them with a debugger attached, but not without).
Perhaps what you're looking for is Environment.Exit(int errorcode)
That behavior is by design.
But there is a work-around.
Either you call Process.GetCurrentProcess().Kill(); within the handler, or simply do not let the handler end.
Check out the example:
class Program
{
void Run()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Console.WriteLine("Press enter to exit.");
do
{
(new Thread(delegate()
{
throw new ArgumentException("ha-ha");
})).Start();
} while (Console.ReadLine().Trim().ToLowerInvariant() == "x");
Console.WriteLine("last good-bye");
}
int r = 0;
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Interlocked.Increment(ref r);
Console.WriteLine("handled. {0}", r);
Console.WriteLine("Terminating " + e.IsTerminating.ToString());
Thread.CurrentThread.IsBackground = true;
Thread.CurrentThread.Name = "Dead thread";
while (true)
Thread.Sleep(TimeSpan.FromHours(1));
//Process.GetCurrentProcess().Kill();
}
static void Main(string[] args)
{
Console.WriteLine("...");
(new Program()).Run();
}
}
This should not be a default sink for exceptions, surely.
But this should be done to report exceptions gracefully.
Note: if you're application is a Windows Forms application, don't forget to:
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
... or else the application will terminate, even if you handle the exceptions with the handlers specified by the other answers.

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

Up until now, I just put a try/catch block around the Application.Run in the Program.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?
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.
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;
}
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");
}
You can use NBug library for that. With minimal setup like this:
NBug.Settings.Destination1 = "Type=Mail;From=me#mycompany.com;To=bugtracker#mycompany.com;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());

Catching unhandled exception on separate threads

I am using the following event to catch unhandled exceptions in the main UI thread.
Application.ThreadException
Unfortunately, it does not catch those unhandled errors in seperate threads. I am aware of
AppDomain.CurrentDomain.UnhandledException
However, this seems to shut down the application upon triggering, where as the former does not.
Is there a way to deal with unhandled exceptions on separate threads, without the application closing?
#Ani have already answered your question. Although I don't agree that unhandled exceptions in threads should terminate applications. Using threads usually means that you have some kind of server application. Bringing it down could result in a lot of angry users.
I've written a small piece about proper exception handling: https://coderr.io/exception-handling
You should always catch exceptions for threads. I usually use the following pattern:
void ThreadMethod(object state)
{
try
{
ActualWorkerMethod();
}
catch (Exception err)
{
_logger.Error("Unhandled exception in thread.", err);
}
}
void ActualWorkerMethod()
{
// do something clever
}
It's a whole lot easier to find thread methods that doesn't handle exceptions properly by moving the logic into a seperate method and just keep the try/catch block in the thread method.
Of course you should always handle all exceptions. But if you are currently incapable of doing so, you can try the following:
The application will crash/close after the UnhandledException event handler.
You can just add a delay in the event handler to prevents this. Other threads with no exception (e.g. the main thread) can continue. So the application will not close and can continue. However, the thread with the exception will remain in sleep. And therefor you may get a "memory/thread leak".
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
// Log the exception, display it, etc
Debug.WriteLine((e.ExceptionObject as Exception).Message);
Thread.Sleep(100000000);
}
At this moment there is not a better solution.
You may find to change the config file, but i think that is just as dirty: https://stackoverflow.com/a/15348736
Yes, you have to manually catch exceptions on threads.
However, this code:
void ThreadMethod(object state)
{
try
{
ActualWorkerMethod();
}
catch (Exception err)
{
_logger.Error("Unhandled exception in thread.", err);
}
}
void ActualWorkerMethod()
{
// do something clever
}
can be simplified to this using PostSharp:
[LogExceptions]
void ActualWorkerMethod()
{
// do something clever
}

Categories