Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Good Architecture/Library For Robust Plugin/Addon Management

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 application 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.

like image 342
GWLlosa Avatar asked Mar 31 '11 01:03

GWLlosa


4 Answers

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.

like image 80
oɔɯǝɹ Avatar answered Oct 13 '22 00:10

oɔɯǝɹ


Sounds like you'd want something similar to OSGi for Java -- Is MEF OSGi for .NET? looks like it might fit the bill.

like image 28
A Lee Avatar answered Oct 13 '22 00:10

A Lee


I would go with MEF

http://msdn.microsoft.com/en-us/library/dd460648.aspx

like image 20
Slappy Avatar answered Oct 12 '22 22:10

Slappy


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.

like image 31
BrandonZeider Avatar answered Oct 13 '22 00:10

BrandonZeider