问题描述
我有一个 COM 类 CMyCOMServer
在一个应用程序中实现了 IMyInterface
,两者都具有正确的 GUID.如果请求 IUnknown 或 IMyInterface,CMyCOMServer::QueryInterface
将返回 S_OK(并将自身转换为正确的类型),否则返回 E_NOINTERFACE.
I have a COM class CMyCOMServer
implementing IMyInterface
in one application, both with correct GUIDs. CMyCOMServer::QueryInterface
will return S_OK (and cast itself to the right type) if IUnknown or IMyInterface is requested, otherwise it returns E_NOINTERFACE.
在同一台 PC 上的另一个应用程序中,我调用:
In another app on the same PC, I call:
HRESULT hr = ::CoCreateInstance(__uuidof(CMyCOMServer), 0, CLSCTX_SERVER,
__uuidof(IMyInterface ),(void **)&pInterface);
它返回 E_NOINTERFACE.所以我认为我做错了什么并在 CMyCOMServer::QueryInterface
上添加了一个断点.我发现当CoCreateInstance
被调用时,对于不同的接口会多次触发QueryInterface
:
It returns E_NOINTERFACE. So I assumed I was doing something wrong and added a breakpoint on CMyCOMServer::QueryInterface
. I found that when CoCreateInstance
is called, QueryInterface
is triggered several times for different interfaces:
- 首先,请求 IUnknown - 没问题
- 然后,请求了多个接口,如 IMarshall 等......这些不受支持,因此返回 E_NOINTERFACE
- 最后,请求 IMyInterface.我验证 QueryInterface 返回 S_OK 并按预期将
(IMyInterface *)this
设置为接口指针
- First, IUnknown is requested - no problem
- Then, several interfaces like IMarshall etc are requested... these are not supported so E_NOINTERFACE is returned
- Finally, IMyInterface is requested. I verify QueryInterface returns S_OK and sets
(IMyInterface *)this
as the interface pointer, as expected
所以我的困惑是为什么调用 CoCreateInstance 给我留下一个空指针和 E_NOINTERFACE 的返回代码,而 COM 服务器应用程序显然返回了我要求的接口?
So my confusion is why the calling CoCreateInstance is leaving me a NULL pointer and return code of E_NOINTERFACE, when the COM server app is clearly returning the interface I ask for?
我的客户端应用程序在启动时调用 CoInitialize(NULL),这没有区别.
my client app calls CoInitialize(NULL) at startup, this makes no difference.
推荐答案
如果你的COM服务器运行在不同的进程中,或者同一个进程中的不同套间,COM需要知道如何打包和传输参数调用您的接口.这个过程称为编组".
If your COM server is running in a different process, or a different apartment in the same process, COM needs to know how to package and transmit parameters when you make calls to your interface. This process is called "marshaling".
如果您定义自定义接口,则需要使用以下方法之一为其实现封送处理.
If you define a custom interface, you need to implement marshaling for it using one of the following approaches.
- 标准封送处理:让 MIDL 编译器生成代理和存根,您必须在系统上注册.这可能是最好的选择,因为您已经定义了接口.
- OLE 自动化封送处理:您定义一个自动化兼容自定义界面并使用marshaller 已经是的一部分COM框架
- 自定义封送处理:您实现 IMarshal 的方法
- Standard marshaling: have the MIDL compiler to generate a proxyand stub which you must register on the system. This is probably the best option since you have already defined your interface.
- OLE Automation marshaling: you define an automation compatiblecustom interface and use themarshaller which is already part ofthe COM framework
- Custom marshaling: you implement the methods of IMarshal
当你调试你的 COM 服务器时,虽然你看到你在调用 QueryInterface 时返回你的自定义接口,但它并没有跨越进程边界,因为 COM 无法弄清楚如何封送该接口,因此客户端看到 E_NOINTERFACE.
When you are debugging your COM server, although you see that you are returning your custom interface in the call to QueryInterface, it does not make it across the process boundary because COM cannot figure out how to marshal that interface, hence the client sees E_NOINTERFACE.
更新(根据您的评论)
如果这是一个现有的 COM 服务器应用程序,那么您可能已经有一个代理/存根.您需要在客户端和服务器上注册它.可能是您在一台或多台新机器上测试它而您只是忘记了注册?要注册,您只需在代理/存根 dll 上执行 regsvr32.
If this is an existing COM server app then you probably already have a proxy/stub. You need to register this on both the client and server. Could it be that you were testing this on a new machine(s) and you simply forgot to register this? To register you simply do regsvr32 on the proxy/stub dll.
这篇关于即使找到接口,CoCreateInstance 也返回 E_NOINTERFACE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!