QueryInterface在Windows Vista上失败

时间:2014-06-13 13:58:44

标签: com windows-vista atl

有一个简单的进程外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。

0 个答案:

没有答案