We have an application which, as one of its requirements, will take arbitrary 3rd party plugins, load them, and run their UI alongside our home-grown application. We've been loading these 3rd party plugins into their own AppDomains for isolation purposes, and everything works ok.
Until one of the plugins crashes out with an unhandled exception. In this circumstance, the entire a开发者_运维知识库pplication goes down, even though all that is really affected is one of our 'extra' tool windows.
We'd like, ideally, some way to handle the "unhandled" exception, unload the damaged AppDomain, and then just reload it fresh. The problem is that we can't find a mechanism in the event handler for the unhandled exception whereby we can flag the exception as being 'handled'. Further, since the plugins have their own UI components with their own set of interactions with the user, it would be extremely difficult to "wrap" our interactions with the plugins in try/catch/finally blocks.
Are there any frameworks/programming libraries/patterns that lend themselves to solving this problem? We can do plugin stuff fine; what we need help with is keeping the application alive when code in a different AppDomain fails unexpectedly.
You can use the System.Addin
framework (sometimes known as MAF
), which is a bit of a hassle to set up correctly, but which was designed to provide isolation (crash protection). System.Addin
is based on remoting. With this framework you can let plugins run with limited permissions, in the same process, or in another app-domain, or even in another process.
If you need total crash protection you may need to use the process separation option. It may come at the cost of performance though.
You can use this code to load an addin in a different app domain:
AppDomain addInDomain = AppDomain.CreateDomain("addin domain");
// addInDomain.PermissionSet = ...
AddInEnvironment env = new AddInEnvironment(addInDomain);
// Activate the add-in
IHostView addinInstance = addinToken.Activate<IHostView>(env);
Console.WriteLine(addinInstance.DoSomething());
AppDomain.Unload(addInDomain);
If you want to load the addin into another process, for complete isolation:
AddInProcess process = new AddInProcess();
process.Start();
// Activate the add-in
IHostView addinInstance = addinToken.Activate<IHostView>(process, AddInSecurityLevel.Internet);
try
{
// use a catch block, prevent exceptions from the addin crashing the main app
Console.WriteLine(addinInstance.DoSomething());
}
catch (Exception e)
{
Console.WriteLine(e);
}
process.Shutdown();
This blog gives a good description of setting this up.
It is possible to combine System.Addin
with MEF, these are complimentary toolkits, see this article.
Note that the System.Addin model may provide crash protection, you will still need to deal with slowdowns or deadlocks in the addin code. Asynchronous usage will help here.
Sounds like you'd want something similar to OSGi for Java -- Is MEF OSGi for .NET? looks like it might fit the bill.
I would go with MEF
http://msdn.microsoft.com/en-us/library/dd460648.aspx
I do not think this is possible. My understanding is that even if you handle the AppDomain.UnhandledException event, the application will still terminate. The best you can do is handle the exception, log what you can, save what state that you can, and terminate gracefully.
精彩评论