【问题标题】:C++ COM out-of-proc marshalling data through proxy\stubC++ COM 进程外编组数据通过代理\存根
【发布时间】:2013-08-02 12:11:28
【问题描述】:

我正在尝试在一些 exe 文件和客户端中创建进程外 com 服务器,该客户端将通过proxy\stub 机制访问功能。 我有我的 .idl 文件:

[
    object,
    uuid(eaa27f4f-ad6b-4a52-90f3-6028507751a1),
    dual,
    nonextensible,
    helpstring("IConfig Interface"),
    pointer_default(unique)
]
interface IInterractionInterface : IDispatch
{
    [id(1), helpstring("Testing function")] HRESULT Test([in] long param);
};


[
    uuid(6fde5037-3034-4ae1-8aa7-2ad45e5716e4),
    version(1.0),
    helpstring("Some lib")
]
library SomeLib
{
    importlib("stdole32.tlb");
    importlib("stdole2.tlb");

    [
        uuid(86feabe4-a0a7-45b5-bcd4-f4f7085d6b1f),
        helpstring("Some lib")
    ]
    coclass Interraction
    {
        [default] interface IInterractionInterface;
    };
}

我是使用 midl 编译器生成的 _p.c、_i.c 文件,使用 .def 创建代理\存根 dll:

LIBRARY        proxy_stub.dll
DESCRIPTION    'generic proxy/stub DLL'
EXPORTS        DllGetClassObject      @1 PRIVATE
               DllCanUnloadNow        @2 PRIVATE
               DllRegisterServer      @4 PRIVATE
               DllUnregisterServer    @5 PRIVATE

然后我使用regsrv32注册了这个dll,在win注册表中我有这个:

在我的服务器中,我创建了工厂:

CoRegisterClassObject(CLSID_InterractionInterfaceFactory, (IClassFactory*) &factory, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &regID);

它等待客户端调用。 在客户端,我使用 CreateInstance 调用我的工厂:

result = CoGetClassObject(CLSID_InterractionInterfaceFactory, CLSCTX_LOCAL_SERVER, NULL, IID_IClassFactory, (void**)&factory);

if (S_OK == result)
{
    IInterractionInterface* iface = NULL;

    result = factory->CreateInstance(NULL, IID_InterractionInterface, (void**)&iface);
    if (S_OK == result)
    {

    }
}

客户端收到 null iface,结果为 E_UNEXPECTED,但在工厂中它创建成功,我从 Factory::CreateInstance() 返回 S_OK。 我不明白 PS 机制是否使用我的 .dll?也许我忘记了一些步骤?为什么我的对象不能通过进程边界?

编辑: 我尝试替换客户端代码,现在是:

result = CoCreateInstance(CLSID_InterractionInterfaceFactory, NULL, CLSCTX_LOCAL_SERVER, IID_InterractionInterface, (void**)&iface);
iface->Test(1);

当我试图调用 Test(1) 时,它会抛出一个错误,这是纯虚函数。在 CreateInstance 的工厂中,我收到了 Unkonown 接口的要求。

【问题讨论】:

  • 使用代理/存根需要HCKR\Interfaces 中的注册表项条目,ProxyStubClsId32 值必须设置为代理的 CLSID。目前尚不清楚这是否正确完成。然而,当您遇到注册问题时,E_UNEXPECTED 并不是您所期望的那种错误,而是您会得到 E_NOINTERFACE。尝试使用 SysInternals 的 ProcMon,您可能会更好地了解问题所在。可能是某种 DLL 加载问题。
  • 截图上没有这个路径是 HKEY_CLASSES_TOOR\Wow6432Node\CLSID\{GUID}。不对吗?
  • 没错,只是不是唯一一个。您还需要 extra 键,HKCR\Interfaces 中的每个键用于服务器实现的每个接口。这就是 COM 在被要求编组接口时确定需要使用哪个服务器的方式。您可以在 ProcMon 中轻松看到这一点,推荐。
  • 我使用 ProcMon 发现我的服务器试图(从注册表)读取 Factory 对象的 CLSID 并且不能,因为它没有注册。并且在尝试接收接口实例时没有读取任何注册表。我无法理解它必须如何工作。我需要将一些数据从一个进程发送到另一个进程。我需要一个 factory-createInstance 方案,还是只有一个实例就足够了?但是我如何将已经创建的实例从服务器发送到客户端?
  • 听起来很准确。您的客户端代码应使用 CoCreateInstance() 创建“交互”对象。

标签: c++ com out-of-process


【解决方案1】:

如果您想使用代理/存根 DLL,请在 library 块之外定义接口。只有在library 之外定义的内容才会进入为代理/存根 DLL 生成的代码中。在library 块内定义或引用的内容进入生成的类型库。一个典型的 IDL 文件定义了library 之外的接口,然后在coclass 块中提及​​它们;这种方式接口定义最终在代理/存根和 TLB 中,以获得最大的灵活性。

您的界面与自动化兼容(嗯,几乎;将参数类型从 int 更改为 long)。在这种情况下,您可能更喜欢使用基于类型库的所谓“通用”编组。只需使用 regtlib 工具或以编程方式使用 LoadTypeLibEx 注册 MIDL 生成的 TLB 文件,您就会获得编组支持。

【讨论】:

  • 我更新了我的问题。我在 .idl 文件中的库块之外定义了接口。然后我注册了regtlib,正如你所说,并在客户端代码中进行了一些编辑(查看帖子的底部)。现在我有一个错误,我试图调用的函数是纯虚拟的。我认为那是因为它请求未知接口。
  • 您为什么要对客户端代码进行更改?你的类工厂对象是否真的实现了IInterractionInterface?这将是不寻常的:通常,类工厂实现IClassFactory,其CreateInstance 实现创建一个新对象,该对象又实现所需的接口。
猜你喜欢
  • 2012-10-10
  • 2014-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-01
  • 2012-08-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多