如何使用 .NET 2.0 安全地托管插件

Posted

技术标签:

【中文标题】如何使用 .NET 2.0 安全地托管插件【英文标题】:How to host Plug-ins safely with .NET 2.0 【发布时间】:2011-07-22 14:41:48 【问题描述】:

我正在编写一个允许两个程序竞争的国际象棋游戏,玩家需要编写一个 DLL 并公开一个函数来告诉主应用程序他的玩家下一步将移动到哪里,假设函数如下所示

public static void MoveNext(out int x, out int y, out int discKind);

播放器的 DLL 可以使用 C# 或 C++ 编写。

在国际象棋游戏应用程序中,我启动一个新线程来调用玩家的 DLL 暴露的函数以获取他将在回合中移动的位置,并启动一个计时器以防止玩家超时,如果玩家超时我会按照API杀死对应的线程

thread.Abort();
thread.Join();

我有如下问题:

    线程不能100%被杀死(取决于玩家的代码)

    在测试过程中我发现,如果播放器使用深度递归(如果播放器程序中存在内存泄漏),宿主应用程序的内存使用会增加,然后宿主应用程序将终止任何例外。

有没有什么技术、想法或方法可以处理上述问题?

从此CodeInChaos建议将播放器的DLL加载到单独的域中,然后在必要时将其卸载,我不确定它是否仍然适用于非托管DLL(C++),是否会导致效率低?

【问题讨论】:

【参考方案1】:

AppDomain 中未处理的异常仍会导致您的程序在 .Net 2.0 中终止。您有机会通过事件处理程序响应异常,但无法处理它。

您最好的选择是使用流程来实现您正在寻找的那种隔离。

【讨论】:

能否请您提供更多有关如何使用流程来处理我的问题的详细信息? 您需要创建一个辅助托管进程来启动插件环境,这取决于您的插件模型需要什么。 您需要创建一个辅助托管进程来启动插件环境,这取决于您的插件模型需要什么。然后,您需要使用 IPC 机制将数据传入和传出托管进程。您选择哪种方法取决于您需要来回传递多少数据以及其他原因的频率。 .Net Remoting 和 WCF 是 .Net 特有的两种机制,它们应该使这更容易。共享内存区域、命名管道和 COM 是您可以使用的更多与语言无关的机制,但更复杂,需要更多工作。 游戏托管应用程序和玩家的插件托管应用程序之间使用任何IPC机制进行通信是否存在效率问题,因为它们将相互通信(每个步骤大约有100个步骤)一轮比赛,比赛会有很多轮次) 任何隔离机制都会有相关的成本。基于编组和复制的机制对通信的影响最大,基于共享内存的方法开销最小,但没有隔离/保护性。【参考方案2】:

如果您可以确保您的插件 DLL 始终是托管代码,那么您可以选择在您的主应用程序逻辑中创建一个新的应用程序域并将包含插件的程序集加载到该域中。

然后,您可以选择在该特定应用程序域中捕获未处理的异常,然后您可以选择卸载整个应用程序域。这样你就可以应对其他人的应用程序插件行为不端和抛出异常。您还可以选择指定部分信任以进一步限制插件的功能。

但是,如果您无法强制使用托管代码插件,这将无济于事,而较早的一组单独进程的选项会更合适。

再次阅读您的帖子,您必须使用的插件似乎存在一些质量问题。如果您必须处理这些有问题的插件,我会采纳之前的建议并使用单独的流程。

【讨论】:

以上是关于如何使用 .NET 2.0 安全地托管插件的主要内容,如果未能解决你的问题,请参考以下文章

通俗易懂,C#如何安全高效地玩转任何种类的内存之Span

如何使 .net HttpClient 使用 http 2.0?

如何让 JWT 在 Autorest 生成的 SDK 中工作? (ASP.NET 核心 2.0)

如何在 asp.net Web 应用程序中安全地嵌入 F# 编译器

如何让 OAuth 2.0 正确地在我的自定义 API .net 核心中使用外部 API

从 .Net 2.0 客户端调用 WCF 服务时如何配置安全性