Winapi 标准COM封送拆收器与REGDB_E_IIDNOTREG一起失败
我正在尝试封送一个接口到另一个线程 Windows提供了方便的助手函数来处理与直接使用相关联的样板代码Winapi 标准COM封送拆收器与REGDB_E_IIDNOTREG一起失败,winapi,com,typelib,Winapi,Com,Typelib,我正在尝试封送一个接口到另一个线程 Windows提供了方便的助手函数来处理与直接使用相关联的样板代码 const Guid CLSID_Widget = "{F8383852-FCD3-11d1-A6B9-006097DF5BD4}"; const Guid IID_IWidget = "{EBBC7C04-315E-11D2-B62F-006097DF5BD4}"; //Create our widget HRESULT hr = CoCreateInstance(CLSID_Widge
const Guid CLSID_Widget = "{F8383852-FCD3-11d1-A6B9-006097DF5BD4}";
const Guid IID_IWidget = "{EBBC7C04-315E-11D2-B62F-006097DF5BD4}";
//Create our widget
HRESULT hr = CoCreateInstance(CLSID_Widget, null,
CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
IID_IWidget, out widget);
OleCheck(hr);
//Marshall the interface into an IStream
IStream stm;
hr = CoMarshalInterThreadInterfaceInStream(IID_IWidget, widget, out stm);
OleCheck(hr);
除了调用CoMarshalThreadInterfaceInStream
失败,原因如下:
REGDB_E_IIDNOTREG (0x80040155)
Interface not registered
REGDB_E_IIDNOTREG (0x80040155)
Interface not registered
REGDB_E_IIDNOTREG (0x80040155)
Interface not registered
REGDB_E_IIDNOTREG (0x80040155)
Interface not registered
直接去CoMarshalInterface
COM API函数CoMarshalInterThreadInterfaceInStream为CreateStreamOnHGlobal
和CoMarshalInterface
提供了一个简单的包装器:
所以我们可以自己试试
IStream stm = new Stream()
hr = CoMarshallInterface(stm, IID_IWidget, widget,
MSHCTX_INPROC, // destination context is in-process/same host
NULL, // reserved, must be null
MSHLFLAGS_NORMAL // marshal once, unmarshal once
);
OleCheck(hr);
但这在以下方面是行不通的:
REGDB_E_IIDNOTREG (0x80040155)
Interface not registered
REGDB_E_IIDNOTREG (0x80040155)
Interface not registered
REGDB_E_IIDNOTREG (0x80040155)
Interface not registered
REGDB_E_IIDNOTREG (0x80040155)
Interface not registered
使用标准编组
我的类不实现imarhal
接口。这是正确和正常的
默认情况下,当第一次对对象调用CoMarshalInterface
时,会询问该对象是否希望处理自己的跨单元通信。这个问题以QueryInterface
请求IMarshal
接口的形式出现。大多数对象都没有实现IMarshal
接口,因此失败
QueryInterface
请求,表示他们非常乐意让COM
通过ORPC电话处理所有通信。实现
IMarshal
接口表示ORPC不合适,对象实现者更愿意处理所有跨单元通信
通过自定义代理。当对象实现IMarshal
接口时,对该对象的所有引用都将被自定义封送
当对象未实现IMarshal
接口时,对该对象的所有引用都将被标准封送。大多数对象选择使用标准封送处理
所以问题变成了为什么标准COM封送处理程序有这么多问题?未注册接口的错误来源是什么
实际上,该接口未注册
COM的需求没有记录,但我可以告诉您,我的接口GUID不存在于:
HKEY_CLASSES_ROOT\Interface\{EBBC7C04-315E-11D2-B62F-006097DF5BD4}
原因将在最后解释
我知道Windows为您提供了一个功能,允许您在进程内注册接口,以便标准封送处理程序能够封送它:
使下载的DLL能够在其运行进程中注册其自定义接口,以便封送处理代码能够封送这些接口
HRESULT CoRegisterPSClsid(
_In_ REFIID riid,
_In_ REFCLSID rclsid
);
参数:
[in]:指向要注册的接口的IID的指针riid
[in]:指向DLL的CLSID的指针,该DLL包含riid指定的自定义接口的代理/存根代码rclsid
CoRegisterPSClsid(IID_IWidget, ???);
包含riid指定的自定义接口的代理/存根代码的DLL的CLSID是什么?我是否使用我的类本身
CoRegisterPSClsid(IID_IWidget, CLSID_Widget);
这听起来不太对;但我对COM标准封送员的理解还不够透彻。CLSID不是必须是标准的COM marsharling类之一吗;实现IPSFactoryBuffer
不管怎样,它都不起作用。我仍然收到错误“接口未注册”
注册接口
我当然可以在注册表中注册我的接口:
HKEY_CURRENT_USER\Software\Classes\Interface\{EBBC7C04-315E-11D2-B62F-006097DF5BD4}
(default) = "IWidget"
HKEY_CURRENT_USER\Software\Classes\Interface\{EBBC7C04-315E-11D2-B62F-006097DF5BD4}
(default) = "IWidget"
但这并不能解决问题。通过查看接口
注册表项,我注意到许多注册表项都指定了ProxyStubClsid32项
在对象上请求新接口时,代理和存根管理器
必须将请求的IID解析到接口封送拆收器的CLSID上。
在WindowsNT5.0下,类存储在NT中维护这些映射
目录,并将它们缓存在本地注册表中的每台主机上。这个
计算机范围的IID到CLSID映射缓存在
HKEY_CLASSES_ROOT\Interface
HKEY_CURRENT_USER\Software\Classes\Interface
每个用户的映射缓存在
HKEY_CLASSES_ROOT\Interface
HKEY_CURRENT_USER\Software\Classes\Interface
这些键中的一个或两个将包含每个已知接口的子键。如果接口安装了接口封送处理程序,则会有额外的
指示接口的CLSID的子键(ProxyStubClsid32)
元帅
除了什么类实现封送处理?我没有警长
COM能否基于类型库自动封送
如果我用接口注册一个类型库,COM的标准封送拆收器是否能够动态引导一个代理类
我在上面注册了我的界面。现在,我手动包括TypeLibrary:
HKEY_CURRENT_USER\Software\Classes\Interface\{EBBC7C04-315E-11D2-B62F-006097DF5BD4}\TypeLib
(default) = "{38D528BD-4948-4F28-8E5E-141A51090580}"
HKEY_CURRENT_USER\Software\Classes\Interface\{EBBC7C04-315E-11D2-B62F-006097DF5BD4}\TypeLib
(default) = "{38D528BD-4948-4F28-8E5E-141A51090580}"
如果我在调用CoMarshalInterface
的过程中监视注册表,我会看到它尝试并找到我的接口IID:
- 操作:
RegOpenKey
- 路径:
HKCR\WOW6432Node\Interface\{EBBC7C04-315E-11D2-B62F-006097DF5BD4}
- 结果:
成功
- 操作:
RegOpenKey
- 路径:
HKCR\WOW6432Node\Interface\{668790E3-83CC-47E0-907F-A44BA9A99C8D}\ProxyStubClsid32
- 结果:
未找到名称
- 操作:
RegOpenKey
- 路径:
HKCR\WOW6432Node\Interface\{668790E3-83CC-47E0-907F-A44BA9A99C8D}\TypeLib
HKEY_CURRENT_USER\Software\Classes\Interface\{EBBC7C04-315E-11D2-B62F-006097DF5BD4}
(default) = "IWidget"
HKEY_CURRENT_USER\Software\Classes\Interface\{EBBC7C04-315E-11D2-B62F-006097DF5BD4}\TypeLib
(default) = "{38D528BD-4948-4F28-8E5E-141A51090580}"