无法使用COM互操作中的AppDomain

时间:2009-09-26 17:56:13

标签: .net com-interop appdomain

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

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

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

有两个有些类似的问题herehere,但它们没有给出答案。 什么是错误的想法,或者我如何进一步调试?

1 个答案:

答案 0 :(得分:1)

几年前我遇到了这个问题。 IIRC,问题在于调用堆栈跨越两个appdomain边界,这导致托管obejct的代理被封送两次(COM-> default->你的:new object: - > yours-> default)。通常不是问题,但有一个特殊的接口,.NET COM编组器QIs说“嗨,我是一个托管对象,需要特殊的编组行为”(抱歉,不记得IID-尝试ComTrace或滚动你的拥有IDispatch impl并通过CLR封送它来查看)。这是你被软化的地方 - 当它在默认域中运行时,它知道你被管理然后要求并尝试加载你的托管类型,这只有在你的新域的基础与默认值相同时才会成功。这显然违背了整个目的。

我有几种方法可以解决这个问题。一种方法是使对象创建为异步,因此我可以将托管代理直接推送到新域中的非托管代码(例如,注册非托管回调并直接从新域调用它,绕过默认域)。在addin方案中,这显然很棘手,你无法端到端地控制所有内容。

另一个是让一小段非托管代码滚动一个愚蠢的代理,当.NET封送程序询问“你真的是一个托管对象吗?”时,DID不响应。但是会通过所有其他QI并且IDispatch上的所有内容都不受干扰(我也将我的黑客限制在IDispatch中,这使得它变得更容易)。所以新的序列是:COM-> default->你的:new object-> new proxy wrapper-> default-> COM。

主要PITA-我当时发现了一篇来自CLR互操作团队的人的博客文章,该文章在未来的CLR版本中为此提出了一些可能的解决方案,但是几年前我不记得是谁了。 (对不起,我不再为了生活而互相支持,谢天谢地!)