尝试COM聚合时,为什么会出现ExecutionEngineException

时间:2012-03-27 19:54:36

标签: c# .net com

我正在尝试使用以下代码聚合COM对象(外部未知)中的.NET对象:

Object obj = ... // some ComVisible .NET object

var comObj  = (IMyComInterface)Activator.CreateInstance(Type.GetTypeFromProgID("some.progid"));

var unknown = Marshal.GetIUnknownForObject(comObj);

var innerUnknown = Marshal.CreateAggregatedObject(unknown, obj);

// This is where the ExecutionEngineException is thrown.         
var aggObj = Marshal.GetObjectForIUnknown(innerUnknown);

// Make outer object aware of our dotnet object, say.
comObj.DotNetObj = aggObj;

Marshal.Release(unknown);

...

此代码有“明显”错误吗?这个例外让我很少继续下去。同样令人讨厌的是,异常并不总是发生,尽管它经常发生。 还有另一种方法来实现这一目标吗? (即将innerUnknown IntPtr封送到我的COM对象)

注意:我必须定位框架的第2版并且没有尝试过版本4,据我所知,我完全是最新的。

1 个答案:

答案 0 :(得分:3)

回答这个问题,它失败的原因是innerUnknown是错误的未知。该方法旨在获取COM IUnknown的活动RCW,但此IUnknown是Managed对象的Com-callable包装器。

在任何情况下,外部对象都需要innerUnknown指针。如果你给它一个你想要的那个,你会在QueryInterface中得到一个堆栈溢出。

在上面的示例中,.Net对象认为它已由COM对象聚合,但COM对象无法识别。假设它是你的COM对象,你需要给它innerUnknown,然后实现委托IUnknown(如果你还没有)。您无需调用GetObjectForIUnknown。

然而,你却有点倒退。通常的方法是COM对象调用CoCreateInstance将自身作为外部未知来传递。然后运行时为您调用CreateAggregatedObject。


如果希望.Net对象聚合COM对象,则应该从RCW继承。这将创建COM对象作为聚合对象,将.Net内部未知传递给CoCreateInstance。但它必须是支持聚合的对象。

如果希望COM对象聚合.Net对象,则必须使用COM对象来执行此操作。典型的例子是ADO聚合OLEDB提供商,ADSI聚合ADSI扩展,WMI(我认为)。但它必须得到对象的支持,你无法告诉任何旧对象聚合你。通常它由另一个调用CoCreateInstance的对象发生,该对象由.Net运行时处理,它将为您调用CreateAggregatedObject,并将innerUnknown传递回调用者。