7

我们有一个应用程序,作为其要求之一,它将采用任意 3rd 方插件,加载它们,并与我们自己开发的应用程序一起运行它们的 UI。我们一直在将这些 3rd 方插件加载到他们自己的 AppDomain 中以进行隔离,一切正常。

直到其中一个插件因未处理的异常而崩溃。在这种情况下,整个应用程序都会崩溃,即使真正受到影响的只是我们的“额外”工具窗口之一。

理想情况下,我们希望通过某种方式来处理“未处理”异常,卸载损坏的 AppDomain,然后重新加载它。 问题是我们在事件处理程序中找不到未处理异常的机制,我们可以将异常标记为“已处理”。此外,由于插件有自己的 UI 组件和自己的用户交互集,因此很难将我们与插件的交互“包装”在 try/catch/finally 块中。

是否有任何框架/编程库/模式可以解决这个问题?我们可以很好地做插件; 我们需要帮助的是当不同 AppDomain 中的代码意外失败时保持应用程序处于活动状态。

4

4 回答 4

9

您可以使用System.Addin框架(有时称为MAF),正确设置有点麻烦,但它旨在提供隔离(崩溃保护)。System.Addin基于远程处理。使用这个框架,您可以让插件在同一个进程、另一个应用程序域甚至另一个进程中以有限的权限运行。

如果您需要全面的崩溃保护,您可能需要使用进程分离选项。不过,它可能会以性能为代价。

您可以使用此代码在不同的应用程序域中加载插件:

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);

如果要将插件加载到另一个进程中,以实现完全隔离:

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();

这个博客很好地描述了这个设置。

可以System.Addin与 MEF 结合使用,这些是免费的工具包,请参阅本文

请注意,System.Addin 模型可能提供崩溃保护,您仍然需要处理插件代码中的减速或死锁。异步使用在这里会有所帮助。

于 2011-04-03T17:08:29.013 回答
1

听起来您想要类似于 Java 的 OSGi 的东西—— MEF OSGi 是用于 .NET 的吗?看起来它可能符合要求。

于 2011-03-31T01:09:15.053 回答
1

我会和MEF一起去

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

于 2011-03-31T04:00:43.760 回答
1

我不认为这是可能的。我的理解是,即使你处理了AppDomain.UnhandledException事件,应用程序仍然会终止。你能做的最好的事情就是处理异常,记录你能做的,保存你能做的状态,然后优雅地终止。

于 2011-04-07T16:50:01.637 回答