Winapi 标准COM封送拆收器与REGDB_E_IIDNOTREG一起失败

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

我正在尝试封送一个接口到另一个线程

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_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
);
参数:

  • riid
    [in]:指向要注册的接口的IID的指针
  • rclsid
    [in]:指向DLL的CLSID的指针,该DLL包含riid指定的自定义接口的代理/存根代码
我可以尝试调用它,但我使用什么clsid

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}
  • 结果:
    成功
然后,它尝试查找代理stubclsid32,但失败:

  • 操作:
    RegOpenKey
  • 路径:
    HKCR\WOW6432Node\Interface\{668790E3-83CC-47E0-907F-A44BA9A99C8D}\ProxyStubClsid32
  • 结果:
    未找到名称
我的希望是标准COM封送员尝试查找:

  • 操作:
    RegOpenKey
  • 路径:
    HKCR\WOW6432Node\Interface\{668790E3-83CC-47E0-907F-A44BA9A99C8D}\TypeLib
但事实并非如此

OLE自动化封送处理程序 根据Don Box,Ole自动化封送处理程序(PSOAnterFace-{00020424-0000-0000-C000-0000000000 46})能够从类型库中构建存根/代理:

类型库封送处理程序

当遇到这些特殊注释的接口时
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}"