有一个简单的进程外COM服务器,用接口实例化或从它查询接口IUnknown
可以在 Windows 7上运行某些机器但在 Windows Vista上失败 E_NOINTERFACE
的其他人。
我觉得它必须对编组做些什么,因为我看到QI在服务器端成功了。
界面非常简单,我只更改了一些名称:
[
object,
uuid(3FEE2913-52C7-46DB-B5AA-298263FB5393),
oleautomation,
nonextensible,
helpstring("My ISuperDuper Interface"),
pointer_default(unique)
]
interface ISuperDuper : IUnknown {
HRESULT get_Version([out, retval]BSTR* version_string);
};
exe服务器是用ATL实现的:
class ATL_NO_VTABLE CSuperDuper :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CSuperDuper, &CLSID_SuperDuper>,
public ISuperDuper
{
public:
CSuperDuper(){}
DECLARE_REGISTRY_RESOURCEID(IDR_SUPERDUPER)
DECLARE_NOT_AGGREGATABLE(CSuperDuper)
BEGIN_COM_MAP(CSuperDuper)
COM_INTERFACE_ENTRY(ISuperDuper)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct() {
return WaitForServerStart() ? S_OK : E_FAIL;
}
public:
STDMETHOD(get_Version)(BSTR *version_string) {
CComBSTR version(_T(VERSION_NUMBER_STR_DOT));
return version.CopyTo(version_string);
}
};
客户端代码尝试实例化服务器,但失败并显示E_NOINTERFACE
:
bool StartServer() {
ComInit com(COINIT_MULTITHREADED);
if(SUCCEEDED(com.result) || com.result == RPC_E_CHANGED_MODE) {
CComPtr<ISuperDuper> server;
auto result = server.CoCreateInstance(L"CompanyName.SuperDuper");
LOG_DBG("CoCreateInstance result: " << std::hex << result);
if(server!= nullptr) {
CComBSTR version;
if(SUCCEEDED(server->get_Version(&version)) && version.m_str) {
LOG_DBG("Started server version " << version.m_str);
} else {
LOG_WRN("Failed to get version from server");
}
} else {
LOG_ERR("Failed to start Server");
}
return server != nullptr;
} else {
LOG_ERR("Failed to initialize COM: " << std::hex << com.result);
return false;
}
}
此版本首先成功创建IUnknown
,但未能完成QI:
CComPtr<IUnknown> server;
auto result = server.CoCreateInstance(L"CompanyName.SuperDuper");
if(server!= nullptr) {
CComQIPtr<IDeviceMonitor> server_if = server;
if(server_if) {
CComBSTR version;
if(SUCCEEDED(server_if->get_Version(&version)) && version.m_str) {
LOG_DBG("Started COM server version " << version.m_str);
} // ...
} else {
LOG_WRN("Failed to QI server");
}
}
请再次注意这适用于 Windows 7及以上某些机器。在 Windows Vista 的某些机器上,某些机器返回它的ISuperDuper
并且它到达另一个进程。
编辑:我收到了一些质量保证报告,除了Visa之外的其他机器上看到类似的东西,所以我不确定这只与Vista有关。我可以在Vista机器上重现这一点。
我被困住了。有什么想法吗?
编辑2: 假设这是一个编组问题,您如何调试问题以找到原因并提出解决方案?
编辑3: 服务器的安装是按用户进行的。 typelib是在exe中链接的,我们使用标准的ATL exe服务器注册来完成工作。它注册了以下内容:
HKCR\AppId\...
HKCR\MyCompany.SuperDuper
中的服务器注册到其CLSID。HKCR\CLSID\<CLSID>
中注册CLSID并将其指向EXE和Typelib。 Typelib注册了它的LIBID。HKCR\Interface\<IID>
中注册接口,并将其连接到带有LIBID的typelib。HKCR\Typelib\<LIBID>
中注册typelib。指向正确的exe。我仔细检查了受影响的计算机上是否存在这些条目并且它失败了。我还检查了类型库实际上是在exe。