Logging of handled exceptions - c#

I am developing a WPF .net 3.5 application which is using other modules/libraries created within a company. Not all of them support logging and sometimes the information about handled exceptions may be quite useful to find out what's wrong.
So the question is if I can get any notification or hookup somehow for handled events in other modules?
Thanks.

In net 4.0 and above, there is a solution:
The event AppDomain.FirstChanceException fires before any catch block is executed.
This MSDN article has some examples.
Basically you just add an event handler like this:
AppDomain.CurrentDomain.FirstChanceException +=
(object source, FirstChanceExceptionEventArgs e) =>
{
Console.WriteLine("FirstChanceException event raised in {0}: {1}",
AppDomain.CurrentDomain.FriendlyName, e.Exception.Message);
};

There are two events, Application.DispatcherUnhandledException and AppDomain.CurrentDomain.UnhandledException, which might help you. Otherwise, I think, you are out of luck, especially if the modules handle the exceptions themself. Only way would be to attach a debugger, as First-Chance exceptions show up there.

Related

Application.ThreadException vs AppDomain.UnhandledException

First some background: I have a multi-threaded WinForms application that is doing interop to native dlls. This application crashes sometimes with unhandled exception and we are trying to investigate why does it happen. In order to facilitate it, I am creating a global exception handler and I plan to generate process dumpfile from it.
Now coming towards question: as of now this application has handler for Application.ThreadException but it still crashes with unhandled exception. I am thinking of adding a handler for AppDomain.UnhandledException also although I am not sure if its going to help. Are there any possible unhandled exception in this scenario that will not be caught by Application.ThreadException?
Yes, Application.ThreadException can only trap exceptions that are raised in the UI thread. In code that's run due to Windows notifications. Or in technical terms, the events that are triggered by the message loop. Most any Winforms event fit this category.
What it does not trap are exceptions raised on any non-UI thread, like a worker thread started with Thread.Start(), ThreadPool.QueueUserWorkItem or a delegate's BeginInvoke() method. Any unhandled exception in those will terminate the app, AppDomain.UnhandledException is the last gasp.
Going further down-hill, hardware exceptions that are raised in an unmanaged thread by native code that never made any managed CLR call can not be detected with any CLR mechanism. An AccessViolation (exception code 0xc0000005) is the most common cause of death. The only way to trap those is through the Windows API, SetUnhandledExceptionFilter(). This is hard to get right.
You can disable Application.ThreadException with Application.SetUnhandledExceptionMode(). Which is a wise thing to do, giving the user the Continue option doesn't make a lot of sense. Now all exceptions in managed threads behave the same, use AppDomain.UnhandledException to log them.
Application.ThreadException will only be raised for unhandled exceptions on WinForms UI threads (see here.) Adding a handler for AppDomain.UnhandledException could help in this case (though with some caveats, as described in the remarks section here.)
I highly recommend that you use the OS minidump generation instead of your own. This is for several reasons:
Generating a minidump from within the same process is extremely problematic and not always possible.
By the time ThreadException or UnhandledException is started, the exception stack has already been unwound. Generating a minidump at that point will just point you to the handler, not the source of the exception.
If your app is in the field, use WER. If you're doing in-house testing, use ProcDump. You can also just copy the minidump file while the Error Reporting dialog is active.
P.S. There are some exceptional conditions - most notably when doing p/Invoke - where neither ThreadException nor UnhandledException will work.
P.P.S. If you have a debuggable scenario, then try turning on the Managed Debugging Assistants relating to p/Invoke.

.NET Runtime Error causes process to crash! But there's no unhandled exception - Why? CLR bug?

I have a .Net process which runs 24/7 which crashes once or twice per week. I have the AppDomain.CurrentDomain.UnhandledException event hooked up to log4net and the event never gets fired! The process just crashes with logging anything! This looks like a .Net runtime/CLR bug as I just get a message in the Event Log saying ".NET Runtime 2.0 Error".
I am running .Net 3.0 Sp1.
Can some please help me figure out how to fix this?
Event log message:
.NET Runtime 2.0 Error Type: Error Event Id: 1000
Event log description: Faulting application appName.exe, version 0.0.0.0, stamp 4ca5d33d, faulting module mscorwks.dll, version 2.0.50727.3607, stamp 4add5446, debug? 0, fault address 0x0010724e.
I believe that a StackOverflowException would not be caught like this, as there's nowhere for the code to run. This would possibly be a good candidate for something that occurs on a reasonably regular basis - you may need to check through your code for infinite loops/recursion.
Maybe here is your solution
So, some interesting feedback, but it may also be worth mentioning that different application types may throw exceptions on different event handlers.
For a Windows Service, we should be safe handling
static void Main (string[] args)
{
AppDomain.CurrentDomain.UnhandledException +=
CurrentDomain_UnhandledException;
}
For a WinForms application, we should also handle the additional unhandled event handler
static void Main (string[] args)
{
AppDomain.CurrentDomain.UnhandledException +=
CurrentDomain_UnhandledException;
System.Windows.Forms.Application.ThreadException +=
Application_ThreadException;
}
For a WPF application, a dispatcher event is provided for GUI exceptions
static void Main (string[] args)
{
AppDomain.CurrentDomain.UnhandledException +=
CurrentDomain_UnhandledException;
Application.Current.DispatcherUnhandledException +=
Application_DispatcherException;
}
Also worth re-iterating, any unhandled exception typically results in program termination. Handling these events however gives us a chance to report and identify the root error.
Additional links that may help
My question regarding unhandled GUI exceptions (duplicate)
WPF global exception handler
Try to place a global try // catch on the entry point of your application.
Hope it helps.
Here it's talking about this error: http://social.msdn.microsoft.com/Forums/en/clr/thread/2d10da32-3f57-4f9b-a509-e9864fc5bd16
look at under error message 2, also a hot fix included, this might or might not be your problem http://code.msdn.microsoft.com/KB913384

Application.ThreadException for ALL exception? Not just un-trapped ones?

I'm trying to create a top level exception capture for a debug version of some real-time data capture software and was wondering if there was a top-level exception handler similar to Application.ThreadException that captures ALL exceptions, not just unhandled/trapped ones.
Thanks in advance
If you only want to be notified of all exceptions, you can use the AppDomain.FirstChanceException event.
Note: This is only available in .NET 4.0.
ALL exceptions inherit System.Exception. This would be your top-level that you can trap on.

Exception handling for events

I apologize if this is a simple question (my Google-Fu may be bad today).
Imagine this WinForms application, that has this type of design: Main application -> shows one dialog -> that 1st dialog can show another dialog. Both of the dialogs have OK/Cancel buttons (data entry).
I'm trying to figure out some type of global exception handling, along the lines of Application.ThreadException. What I mean is:
Each of the dialogs will have a few event handlers. The 2nd dialog may have:
private void ComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
AllSelectedIndexChangedCodeInThisFunction();
}
catch(Exception ex)
{
btnOK.enabled = false; // Bad things, let's not let them save
// log stuff, and other good things
}
}
Really, all the event handlers in this dialog should be handled in this way. It's an exceptional-case, so I just want to log all the pertinent information, show a message, and disable the okay button for that dialog.
But, I want to avoid a try/catch in each event handler (if I could). A draw-back of all these try/catch's is this:
private void someFunction()
{
// If an exception occurs in SelectedIndexChanged,
// it doesn't propagate to this function
combobox.selectedIndex = 3;
}
I don't believe that Application.ThreadException is a solution, because I don't want the exception to fall all the way-back to the 1st dialog and then the main app. I don't want to close the app down, I just want to log it, display a message, and let them cancel out of the dialog. They can decide what to do from there (maybe go somewhere else in the app).
Basically, a "global handler" in between the 1st dialog and the 2nd (and then, I suppose, another "global handler" in between the main app and the 1st dialog).
Yes, the default handling of Application.ThreadException was a mistake. Unfortunately, it was a necessary mistake, needed to not immediately discourage and despair hundreds of thousands of programmers writing their first Windows Forms application.
The fix you are contemplating is not a fix, it has a lot of potential to make it worse. While a user clicking the Continue button on the exception dialog is a questionable outcome, swallowing exceptions in a global exception handler is much worse.
Yes, do write a replacement handler for ThreadException. Have it display the value of e.Exception.ToString() in a message box so the user has some idea what blew up. Then fire off an email or append to an error log so you know what went wrong. Then call Environment.FailFast() so no more damage can be done.
Do the same for AppDomain.CurrentDomain.UnhandledException. It won't get much of a workout.
Use the feedback to improve your code. You'll find out where validation is required. You can help the customer's IT staff diagnose trouble with their LAN and equipment. And you'll find the very few cases where your own try/catch blocks might be able to recover from the exception.
You may be able to use the AppDomain.CurrentDomain.UnhandledException handler to intercept the errors on the main UI thread and handle them per-dialog. From MSDN:
In applications that use Windows
Forms, unhandled exceptions in the
main application thread cause the
Application.ThreadException event
to be raised. If this event is
handled, the default behavior is that
the unhandled exception does not
terminate the application, although
the application is left in an unknown
state. In that case, the
UnhandledException event is not
raised. This behavior can be changed
by using the application configuration
file, or by using the
Application.SetUnhandledExceptionMode
method to change the mode to
UnhandledExceptionMode.ThrowException
before the ThreadException event
handler is hooked up. This applies
only to the main application thread.
The UnhandledException event is raised
for unhandled exceptions thrown in
other threads.
You may like to rethink the design of your application slightly if you're doing stuff in combobox event handlers that might throw exceptions.
An alternative would be to initialise the dialog with all the information it needs before showing it to the user. The user then makes selections, and presses OK, and then the parent dialog could process the information in the dialog.
The exception handling could then be done in the parent dialog.
Of course this wouldn't be appropriate if you need to dynamically update the data in the dialog based on user actions...
e.g.
MyDialog myDialog = new MyDialog();
myDialog.Init(//data for the user to choose/manipulate);
if(myDialog.ShowDialog() == DialogResult.OK)
{
try{
ProcessDialogData(myDialog.SomeDataObject);
}
catch(/*...*/}
}
HTH
Global exception handling in WinForms application is done using two handlers: Application.ThreadException and AppDomain.CurrentDomain.UnhandledException. ThreadException catches unhandled exceptions in the main application thread, while CurrentDomain.UnhandledException catches unhandled exceptions in all other threads. Global exception handling may be used for the following purposes: showing user-friendly error message, logging the stack trace and other useful information, cleanup, sending error report to developer. After unhandled exception is catched, application should be terminated. You may want to restart it, but it is impossible to correct an error and continue, at least, in non-trivial applications.
Global exception handling is not replacement for local exception handling, which still should be used. Local exception handlers should never use catch Exception, because this effectively hides programming bugs. It is necessary to catch only expected exceptions in every case. Any unexpected exception should crash the program.
Sounds like you want aspects. PostSharp could help you out.

Unhandled Exception Handler in .NET 1.1

I'm maintaining a .NET 1.1 application and one of the things I've been tasked with is making sure the user doesn't see any unfriendly error notifications.
I've added handlers to Application.ThreadException and AppDomain.CurrentDomain.UnhandledException, which do get called. My problem is that the standard CLR error dialog is still displayed (before the exception handler is called).
Jeff talks about this problem on his blog here and here. But there's no solution. So what is the standard way in .NET 1.1 to handle uncaught exceptions and display a friendly dialog box?
Jeff's response was marked as the correct answer because the link he provided has the most complete information on how to do what's required.
Oh, in Windows Forms you definitely should be able to get it to work. The only thing you have to watch out for is things happening on different threads.
I have an old Code Project article here which should help:
User Friendly Exception Handling
Unhandled exception behavior in a .NET 1.x Windows Forms application depends on:
The type of thread that threw the exception
Whether it occurred during window message processing
Whether a debugger was attached to the process
The DbgJitDebugLaunchSetting registry setting
The jitDebugging flag in App.Config
Whether you overrode the Windows Forms exception handler
Whether you handled the CLR’s exception event
The phase of the moon
The default behavior of unhandled exceptions is:
If the exception occurs on the main thread when pumping window messages, it's intercepted by the Windows Forms exception handler.
If the exception occurs on the main thread when pumping window messages, it will terminate the app process unless it's intercepted by the Windows Forms exception handler.
If the exception occurs on a manual, thread-pool, or finalizer thread, it's swallowed by the CLR.
The points of contact for an unhandled exception are:
Windows Forms exception handler.
The JIT-debug registry switch DbgJitDebugLaunchSetting.
The CLR unhandled exception event.
The Windows Form built-in exception handling does the following by default:
Catches an unhandled exception when:
exception is on main thread and no debugger attached.
exception occurs during window message processing.
jitDebugging = false in App.Config.
Shows dialog to user and prevents app termination.
You can disable the latter behavior by setting jitDebugging = true in App.Config. But remember that this may be your last chance to stop app termination. So the next step to catch an unhandled exception is registering for event Application.ThreadException, e.g.:
Application.ThreadException += new
Threading.ThreadExceptionHandler(CatchFormsExceptions);
Note the registry setting DbgJitDebugLaunchSetting under HKEY_LOCAL_MACHINE\Software.NetFramework. This has one of three values of which I'm aware:
0: shows user dialog asking "debug or terminate".
1: lets exception through for CLR to deal with.
2: launches debugger specified in DbgManagedDebugger registry key.
In Visual Studio, go to menu Tools → Options → Debugging → JIT to set this key to 0 or 2. But a value of 1 is usually best on an end-user's machine. Note that this registry key is acted on before the CLR unhandled exception event.
This last event is your last chance to log an unhandled exception. It's triggered before your Finally blocks have executed. You can intercept this event as follows:
AppDomain.CurrentDomain.UnhandledException += new
System.UnhandledExceptionEventHandler(CatchClrExceptions);
AppDomain.UnhandledException is an event, not a global exception handler. This means, by the time it is raised, your application is already on its way down the drain, and there is nothing you can do about it, except for doing cleanup and error logging.
What happened behind the scenes is this: The framework detected the exception, walked up the call stack to the very top, found no handlers that would recover from the error, so was unable to determine if it was safe to continue execution. So, it started the shutdown sequence and fired up this event as a courtesy to you so you can pay your respects to your already-doomed process. This happens when an exception is left unhandled in the main thread.
There is no single-point solution to this kind of error. You need to put a real exception handler (a catch block) upstream of all places where this error occurs and forward it to (for example) a global handler method/class that will determine if it is safe to simply report and continue, based on exception type and/or content.
Edit: It is possible to disable (=hack) the error-reporting mechanism built into Windows so the mandatory "crash and burn" dialog does not get displayed when your app goes down. However, this becomes effective for all the applications in the system, not just your own.
Is this a console application or a Windows Forms application? If it's a .NET 1.1 console application this is, sadly, by design -- it's confirmed by an MSFT dev in the second blog post you referenced:
BTW, on my 1.1 machine the example from MSDN does have the expected output; it's just that the second line doesn't show up until after you've attached a debugger (or not). In v2 we've flipped things around so that the UnhandledException event fires before the debugger attaches, which seems to be what most people expect.
It sounds like .NET 2.0 does this better (thank goodness), but honestly, I never had time to go back and check.
It's a Windows Forms application. The exceptions that are caught by Application.ThreadException work fine, and I don't get the ugly .NET exception box (OK to terminate, Cancel to debug? who came up with that??).
I was getting some exceptions that weren't being caught by that and ended up going to the AppDomain.UnhandledException event that were causing problems. I think I've caught most of those exceptions, and I am displaying them in our nice error box now.
So I'll just have to hope there are not some other circumstances that would cause exceptions to not be caught by the Application.ThreadException handler.
The Short Answer,
Looks like, an exception occurring in Form.Load doesn't get routed to Application.ThreadException or AppDomain.CurrentDomain.UnhandledException without a debugger attached.
The More accurate Answer/Story
This is how I solved a similar problem. I can't say for sure how it does it, but here is what I think. Improvement suggestions are welcome.
The three events,
AppDomain.CurrentDomain.FirstChanceException
AppDomain.CurrentDomain.UnhandledException
and Application.ThreadException
accumulatively catch most of the exceptions but not on a global scope (as said earlier). In one of my applications, I used a combination of these to catch all kinds of exceptions and even the unmanaged code exceptions like DirectX exception (through SharpDX). All exceptions, whether they are caught or not, seem to be invoking FirstChanceException without a doubt.
AppDomain.CurrentDomain.FirstChanceException += MyFirstChanceExceptionHandler;
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); // not sure if this is important or not.
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; // can't use Lambda here. need to Unsub this event later.
Application.ThreadException += (s, e) => MyUnhandledExceptionHandler(e.Exception);
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MyUnhandledExceptionHandler((Exception)e.ExceptionObject);
}
private void CurrentDomain_FirstChanceException(object sender, System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs eventArgs)
{
// detect the pattern of the exception which we won't be able to get in Fatal events.
if (eventArgs.Exception.Message.StartsWith("HRESULT"))
MyUnhandledExceptionHandler(eventArgs.Exception);
}
and the handler looks like
static void MyUnhandledExceptionHandler(Exception ex)
{
AppDomain.CurrentDomain.UnhandledException -= MyUnhandledExceptionHandler; // this is important. Any exception occuring in the logging mechanism can cause a stack overflow exception which triggers the window's own JIT message/App crash message if Win JIT is not available.
// LogTheException()
// Collect user data
// inform the user in a civil way to restart/close the app
Environment.Exit(0);
}
Unmanaged code exceptions like DirectX exceptions appeared only in FirstChanceException where I had to decide for myself if the exception was fatal or not. I then use MyUnhandledExceptionHandler to log and let the user know in a friendly way that everything was "under control".
IMPORTANT NOTE!
The scheme still didn't catch one kind of exception. It did appear in FirstChanceException, but it was hard to distinguish it from other kinds of exceptions hitting this handler. Any exception occurring directly in Form.Load had this different behavior. When the VS debugger was attached, these were routed to the UnhandledException event. But without a debugger, an old-school windows message will pop up, showing the stack trace of the exception that occurred. The most annoying thing was that it didn't let MyUnhandledExceptionHandlerr get kicked once it was done and the app continued to work in an abnormal state. The final solution I did was to move all the code from Form_load to another thread using MyForm.Load += (s,e) => new Thread(()=>{/* My Form_Load code*/ }).Start();. This way, Application.ThreadException gets triggered which is routed to MyUnhandledExceptionHandler, my safe exit.

Categories