【问题标题】:Failure to use AppDomain from COM interop无法从 COM 互操作中使用 AppDomain
【发布时间】:2009-09-26 17:56:13
【问题描述】:

我有一段 .NET 代码,由于各种原因(可靠性、部署)必须在单独的 AppDomain 中运行。我创建了一个从 MBR 派生的代理对象,它将调用委托给真实的东西,因此它不会加载到当前的 AppDomain 中。我通过通常的 CreateInstanceAndUnwrap 创建代理。

this.eDirectCommunication = (EDirectCommunicationProxy) this.appDomain.CreateInstanceAndUnwrap(x, y);

当我从 .NET 客户端使用它时效果很好,但是当从 COM 客户端加载时,转换失败。我无法从透明代理进行投射。我验证了所需的类型是在所需的 AppDomain 上创建的,并且 Unwrap 成功,只是强制转换失败。有趣的是,当两个 AppDomain 具有相同的基目录时,它确实有效,这表明程序集绑定失败。但是 Fusion 日志查看器没有提及任何问题。

herehere 有两个有点相似的问题,但它们没有提供答案。 任何想法出了什么问题,或者我该如何进一步调试?

【问题讨论】:

    标签: .net com-interop appdomain


    【解决方案1】:

    几年前我遇到了这个确切的问题。 IIRC,问题在于调用堆栈跨越了两个 appdomain 边界,这导致托管对象的代理被封送两次(COM->default->yours:new object:->yours->default)。通常不是问题,但是 .NET COM 封送处理程序 QI 有一个特殊的接口,上面写着“嗨,我是一个托管对象,需要特殊的封送处理行为”(抱歉,不记得 IID-尝试 ComTrace 或滚动你的自己的 IDispatch impl 和 marshal 它通过 CLR 来查看)。这就是你被淹没的地方——当它在默认域中运行时,它知道你是受管理的,然后请求并尝试加载你的托管类型,只有当你的新域的 basedir 与默认值相同时才会成功。这显然违背了整个目的。

    我有几种方法来处理这个问题。一种方法是使对象创建异步,以便我可以将托管代理直接推送到来自新域的非托管代码(例如,注册一个非托管回调并直接从新域调用它,绕过默认域)。在您无法端到端控制所有内容的插件场景中,这显然很棘手。

    另一个是有一小段非托管代码滚动一个愚蠢的代理,当 .NET 封送器询问“你真的是一个托管对象吗?”时它没有响应。但会不受干扰地通过所有其他 QI 和 IDispatch 上的所有内容(我也将我的 hack 限制为 IDispatch,这使得它更容易)。所以新的顺序是:COM->default->yours:new object->new proxy wrapper->default->COM。

    Major PITA - 当时我发现 CLR 互操作团队中的一个人发表的一篇博文在未来的 CLR 版本中提出了一些可能的修复方案,但那是几年前的事了,我不记得是谁了(对不起,我不再以互操作为生了,谢天谢地!)

    【讨论】:

      猜你喜欢
      • 2022-01-22
      • 1970-01-01
      • 1970-01-01
      • 2012-07-10
      • 2010-12-24
      • 1970-01-01
      • 2012-06-26
      • 1970-01-01
      • 2010-09-19
      相关资源
      最近更新 更多