Use AppDomain.UnhandledException in modular forms application - c#

I am currently developing a .NET application completely modular, in which:
There is the host applicaiton that loads module DDLs. The module DDLs have forms that can be opened several times.
You can unload the application domain. This will cause all the opened forms of the module to be closed.
What I want to do is to, when an unhandled exception happens in the module, the application should unload the DDL of that module and prevent the Host to crash.
I tried to use the AppDomain.UnhandledException Event, which has a handler assigned to it right after the creation of the
AppDomain as follows:
// Creates the ApplicationDomain
this._applicationDomain = AppDomain.CreateDomain(this.AppDomainName);
this._applicationDomain.UnhandledException += new UnhandledExceptionEventHandler(_applicationDomain_UnhandledException);
The problem is: that the handler is never called. Microsoft says here that
For example, suppose a thread starts in application domain "AD1", calls a method in application domain "AD2", and from there calls a method in application domain "AD3", where it throws an exception. The first application domain in which the UnhandledException event can be raised is "AD1". If that application domain is not the default application domain, the event can also be raised in the default application domain.
Even after I assign the handler, the exception still goes to
Application.Run(new HostForm());
I suppose that, if I created a new message loop for each module's form it would work, because then the thread in which the form would be running would be a separated thread, but it seems to be a stupid solution.
Another idea I had was to use than the AppDomain.UnhandledException Event of the default application domain, but how can I then:
Discover the AppDomain of origin and therefore the module to unload?
Prevent the Application to die? (I tried doing this and the e.IsTerminating comes with true value and the exception is still caught in the
Anyone? Please, I really need it.

There's a reasonably good explanation (with supporting links) about why the AppDomain.CurrentDomain.UnhandledException handler doesn't suppress unhandled exceptions here. The MSDN article you linked to also describes this behaviour just below the part you quoted.
In the .NET Framework versions 1.0 and 1.1, an unhandled exception
that occurs in a thread other than the main application thread is
caught by the runtime and therefore does not cause the application to
terminate. Thus, it is possible for the UnhandledException event to be
raised without the application terminating. Starting with the .NET
Framework version 2.0, this backstop for unhandled exceptions in child
threads was removed, because the cumulative effect of such silent
failures included performance degradation, corrupted data, and
lockups, all of which were difficult to debug.
So even if you could get the event to fire, it isn't likely to satisfy your requirement that the application not be terminated shortly afterwards. The UnhandledException handler is really only there to give you one last chance to log important information before the application is terminated.
The most resilient applications (Google Chrome for instance) will use full process isolation to ensure anything that goes wrong in a plugin tears down the external plugin host, not the main application. I've used this mechanism myself to create an application similar to the one you describe, and even went to the extent of creating sandboxed AppDomain's inside each external plugin host to ensure plugins couldn't delete critical files if the main application was elevated.
There's a really good article here that describes isolation techniques in detail and reiterates that the AppDomain plugin system isn't the best option due to the UnhandledException problem. If you're serious about a fault tolerant plugin architecture I'd recommend implementing full process isolation as described in that last article.

Related

Robust exception handling in console application

If I put AppDomain.CurrentDomain.UnhandledException code in console application apart from usual try-catch to catch unhandled exceptions. That means, is it sure that any exception will not force application to terminate in between?
If not, what type of exceptions are out of scope of it?
No. It means that you will have the chance to run some code before your application crashes, but you will not be able to prevent the crash. Documentation:
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.
Trying to make the application "crash-proof" by blindly catching all exceptions is a fool's errand: since you don't really know what went wrong, how do you know that it's OK for the program to continue running?
Theoretically speaking, anything you do inside the event handler might go wrong in any possible manner (since an unhandled exception was thrown, and you don't know what it is, it could be anything). So not only is it impossible to prevent the application from crashing, but you should also be very careful about what you do inside the handler.
No, the application will be terminated anyway, but it gives you a chance to log the exception properly before the application exits. See here: http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx
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.

Any way to catch exceptions from any spawned thread?

I am developing an app that has plugin support. Plugins may be developed by third parties.
Currently I have a try/catch handler around any calls into the plugins to try and protect my app from third party code. The catch logs the problem but does not crash my app.
My problem is when the third party code spawns threads to do some work. These are not caught by my handler.
Is there any way to catch exceptions from "anything spawned by this function"? Or do I need to just catch them in my global handler?
When an plugin fails and runs within the same AppDomain, it is best to let the application fail itself; thus, stop the application. You won't know in what state the application is when a plugin crashes.
Another option is to run a plugin in its own (child) AppDomain. This way you can unload that app domain and restart that plugin in a newly created AppDomain, without having to restart the application.
You might want to take a look at the Managed Extensibility Framework (MEF). That is especially designed for these scenarios.
Regarding your second wish - catching the exception in a global handler, you can subscirbe the the UnhandledException event in the application domain. It'll catch all exceptions that were not caught in your code.
It is used mainly to log the information of the exception. It won't, however, save your application from terminating.

Does the System.Diagnostics.Process.Exited Event Always Fire?

I have an application that I am writting that communicates with a third-party program through a COM connection. I was tasked to strengthen the resilency of our application, in order to do that I wait until the third-party application is ready. I do this by waiting until the return value on a method that returns true only when the third-party application has been fully loaded.
In an effort to avoid the condition where the application crashes during this procedure, and my application just sits there waiting throwing COM errors( caught of course ) I was wondering if the Exited event on the Process itself, is guaranteed to always happen?
I am more then willing to provide additional details when its possible. I am also for the time being limited to .NET Framework 2.0 with this current build.
It depends on the sort of crash - some crashes leave the "process" in memory (for example just stuck in some never-ending loop OR that COM object opened some modal error dialog and waits for user)... these cases are not covered by any method mentioned in your description...
In my experience to be really resilient you need a combination:
hook the Exited event (if you started the application via Process) OR find the process ID and monitor that
catch any exceptions from that COM object
implement a timeout + abort logic for calls to that COM object/application
"monitor" the COM object/app
I usually start a separate thread before calling such a COM object... that thread monitors the COM object/application for example if it open any window it is not supposed or memory consumption goes through the roof when it is not supposed to etc. - the things monitored and the reaction to each of them is rather specific to that COM object/application...

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.

Avoid "program stopped working" in C#/.NET

I have a console application written in C#/.NET that I want to run from a script (nant). If an exception occurs in the console application, I would like nant to continue, but in Windows Vista there is a popup that searches for solutions and asks for debug etc.
I would like to avoid the popup with "program stopped working" when an exception happens in the console application. How can I control this from C#/.NET?
(A similar question addresses the issue for the C language, but I would like a solution for C#/.NET.)
(To clarify: I would like the exception to be passed to nant, but without the popup.)
The JIT debugger popup occurs when there's an unhandled exception. That is, an exception tunnels all the way up the stack to the root of any thread in the runtime.
To avoid this, you can handle the AppDomain.CurrentDomain.UnhandledException event and just call Environment.Exit(1) to exit gracefully.
This will handle all exceptions on all threads within your AppDomain. Unless you're doing anything special, your app probably only has one AppDomain, so putting this in your public static void Main method should suffice:
AppDomain.CurrentDomain.UnhandledException += (sender, args) =>
{
Console.Error.WriteLine("Unhandled exception: " + args.ExceptionObject);
Environment.Exit(1);
};
You should probably use the NAnt logger to write out the error in this case too (can't recall the API for this offhand though.)
You can also disable JIT debugging on the machine. I would only recommend this in certain circumstances such as for a dedicated build server.
Under Windows Vista you can disable this dialog for your programms.
Disable the "Problem Reports and Solutions feature". You find it under Control Panel-->Problem Reports and Solutions-->Change Settings-->Advanced Settings-->Turn off for my programs, problem reporting
Just catch the exception and log/ignore it.
The popup appears due to an unhandled exception. To avoid that make sure your main method captures all exceptions and turn them into some other useful piece of info you can pick up. Just ignoring the exception is not recommended.
Btw remember that exceptions are per thread, so if your application spawns threads or uses thread pool threads, you need a handler for these too.
Usually this only happens when your app doesnt handle an exception. If you wrap your whole console app in a try/catch bblock, and just pass back a fail code, then you will avoid this.
Sometimes, a windows application will stop working if you are using a System.Timers.Timer.
To fix this, change System.Timers.Timer by System.Windows.Forms.Timer
Greetings

Categories