7

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.

GWLlosa
  • 23,995
  • 17
  • 79
  • 116

4 Answers4

9

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.

PaulG
  • 13,871
  • 9
  • 56
  • 78
oɔɯǝɹ
  • 7,219
  • 7
  • 58
  • 69
1

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

Community
  • 1
  • 1
A Lee
  • 7,828
  • 4
  • 35
  • 49
  • Does MEF protect you from plugin crashes? – GWLlosa Mar 31 '11 at 13:49
  • 3
    MEF doesn't intrinsically protect you from plugin crashes, however you can run them in separate application domain. Credit due: http://stackoverflow.com/questions/835182/choosing-between-mef-and-maf-system-addin – Chad Ruppert Apr 02 '11 at 01:48
  • We've tried running code in a different app domain and still had problems; see the question for details. Maybe there's a technique or configuration we're missing to achieve this behaviour? – GWLlosa Apr 04 '11 at 14:12
1

I would go with MEF

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

Slappy
  • 4,042
  • 2
  • 29
  • 41
1

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.

BrandonZeider
  • 8,014
  • 2
  • 23
  • 20
  • This matches our experimentation, yet I see a great multitude of people who claim that running in a seperate appDomain provides Crash Protection / Isolation. Either everyone is wrong, or we're missing something. I'm hoping for the latter. – GWLlosa Apr 07 '11 at 17:26
  • In my experience, the only true isolation is by creating a separate process. It doesn't sound like that an option for you guys though. – BrandonZeider Apr 07 '11 at 18:19