【发布时间】: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, ®ID);
它等待客户端调用。 在客户端,我使用 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