我们在C ++中使用ATL编写了一个32位COM组件。当需要从64位.NET使用它时,我们创建一个COM +应用程序,一切正常。
最近我们注意到Win2k8上的奇怪行为。组件中的COM对象触发事件,我们在.NET代码中处理它。该事件还有一个参数也从非托管代码传递。
以下是澄清的部分定义(IDL表示法):
interface IOurCollectionInterface : IDispatch
{
[propget, restricted, id(DISPID_NEWENUM)]]
HRESULT _NewEnum( [out, retval] IUnknown** result );
}
interface IOurObjectInterface : IDispatch
{
[propget]
HRESULT Collection( [out, retval] IOurCollectionInterface** result );
}
事件处理程序传递一个IOurObjectInterface实例。在里面我们尝试运行foreach()循环。
void onEvent( IOurObjectInterface ourObject )
{
foreach( object element in ourObject.Collection ) {
//do stuff
}
}
代码在 foreach 的行上崩溃,并带有以下消息: IEnumVARIANT的QI在非托管服务器上失败
IEnumVARIANT
肯定是由IOurCollectionInterface::get__NewEnum()
实现返回的对象实现的。上面的代码可以在WinXP和Win2k3上运行,但在Win2k8上没有。
这种行为的原因是什么?
答案 0 :(得分:0)
很难确定。但是会怀疑是一个编组问题。
您是否检查过实际调用了IOurCollectionInterface._NewEnum
的实现?
您使用什么类型的COM编组?如果是typelib,是正确注册的typelib吗?
如果在进程中实现接口,它是否有效?
来自sharptooth的评论:
使用Typelib编组并注册typelib。更糟糕的是,当从同一台机器上的WinForms应用程序调用时,这个东西可以正常工作,但是当从本地用户下运行的NT服务调用时会失败。
如果WinForms应用和服务作为不同的用户运行,请非常仔细地检查安全性。从COM +安全性开始,然后使用Process Monitor检查注册表/文件访问问题(这似乎不太可能,但总是可行的)。
答案 1 :(得分:0)
尝试使用系统帐户运行并检查事件以获取有关错误的更多信息。