views:

207

answers:

7

I've developed a .NET 4 software and I'm ready to send it to beta users. If an unhandled exception is thrown in the software, I would like to catch it, log it and send the logs to me. I've already implemented this functionality and it seems to be running fine when I run it in debug mode with Visual Studio. However, when I've built a release version of the software and installed it, Microsoft .NET Framework starts to catch exceptions before my code. I get a popup with an error message: "Unhandled exception has occurred in a component in your application. If you click Continue, the application will ignore this error and attempt to continue."

To test the crashing, I created a crash down button which throws an exception. This crash down logs itself and the exception handler logs all received unhandled exceptions. When I look at the log of the release version, I can only see the log message from crash down but not from the exception handler.

I've attached my own exception handler with this code:

AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

Is there some way to disable the exception catching of .NET Framework or is there a better way to attach my own exception handler?

UPDATE: I'm using WPF. I'll look into the DispatcherUnhandledException and let you know if it solves the problem.

UPDATE #2: Unfortunately adding handler to Application.Current.DispatcherUnhandledException didn't solve the problem. Apparently this debugging popup is created by JIT (Just-In-Time) debugger which is included with Visual Studio. I'll have to test the software with a "civilian" Windows and see if the exceptions are catched there too.

UPDATE #3: For some reason the Release built with Visual Studio works but the Release built with MSBuild scripts and Dotfuscator does not.

A: 

Would a try ... catch block in Main() help?

Andrew Cooper
this would not take care of unhandled exceptions in other threads.
Patrick Klug
+5  A: 

You haven't specified which framework you're using, but there are other "unhandled exception" events around.

For Windows Forms, there's Application.ThreadException.

For WPF/Silverlight there's Application.DispatcherUnhandledException.

Try one of those two first, and let us know if you're still having problems.

Jon Skeet
+3  A: 

It sounds like the exception is bubbling out to your application's message loop. In Windows Forms, you can handle these by setting up an event handler for Application.ThreadException event. In WPF/Silverlight, the equivalent event would be Application.DispatcherUnhandledException.

You can also put a try/catch in your Main method (if you have one) for good measure but the UI will usually catch the exceptions first as you've noticed.

EDIT

In WPF/Silverlight, set e.Handled = true to prevent the exception from continuing up the stack.

Josh Einstein
+1  A: 

You can look into the AppDomain class and the UnhandledException event and Application.ThreadException event. These will catch unhandled exceptions, as for exceptions you are handling yourself with a try-catch block, you could write a helper class to manage your exceptions and do what you need with them. You could even write a third event in that class for handled exceptions.

David Anderson
they say AppDomain.UnhandledException are for exceptions that you can only log. meaning you cannot fix? but you can still do the e.Handled = true
nathan_hc
A: 

From the documentation of UnhandledException event,

This event provides notification of uncaught exceptions. It allows the application to log information about the exception before the system default handler reports the exception to the user and terminates the application.

It is just a hook method where you can insert your custom code code, before the default error reporting mechanism kicks in. An unhandled exception will always take down your process. It doesn't allow you to replace the whole behavior.

I'd first question the need behind your quest..
The simplest approach is to just adopt a team convention that Main and all Thread Functions have an enclosing try-catch.
There seem to be new types+events(DispatcherUnhandledException) to catch unhandled exceptions, but I'd question if its worth the complexity it drags in. It should be a last-line of defence, not the primary one.
e.g. if an unhandled exception occurs in a different thread, you'd need more code (since exceptions are not routed across threads & it'd just terminate the process).

Gishu
A: 

Ouch... Dotfuscator might generate you an invalid assembly that is not JIT'able. JIT exceptions can never be caught by user code. This is similar to the way you cannot catch StackOverflowException because the runtime cannot guarantee you it can safely recover from the encountered error condition.

Nonetheless, it is very unlikely you get a JIT exception at runtime since there are various stages of validation in between your IL and the JITer. Maybe you got an InvalidProgramException or a BadImageFormatException? If the JITter is really failing this is most likely a bug in the runtime and shouldn't happen.

Anyway, two things you can check:

  1. Run PEVerify on your broken/working assembly and compare the output.
  2. Try NGEN on your broken assembly to see if you can provoke the error.
Johannes Rudolph
A: 

I finally solved the problem. The problem was not caused by listening to wrong exceptions but due to missing a DLL from the released version.

After adding listeners for DispatchedUnhandledException and ThreadException events I no longer got the strange Microsoft .NET Framework popup which allowed the user to continue running the software after exception. However my own exception handling was still broken at this point.

Because the software was already crashing down at the moment when the exception handler was supposed to kick in, I had a catch (Exception) around the exception handler. After removing this catch I finally got the correct error message with release version and added the missing DLLs.

The lesson I learned (again) is: do not use empty catch (Exception) block. It is evil.

Ville Salonen