_com_ptr_t CreateInstance返回REGDB_E_CLASSNOTREG

时间:2016-05-31 12:44:09

标签: c++ com atl

我有一个ATL项目,我需要在CComObjectRootEx::FinalConstruct内执行各种初始化例程。出于演示目的,请考虑以下实现:

HRESULT FinalConstruct()
{
    return m_bInit ? S_OK : E_FAIL;
}

这应该将相应的HRESULT返回给调用者,指示对象的初始化是否成功。

但是,在尝试创建服务器时,如果发生故障,客户端始终会收到REGDB_E_CLASSNOTREG而不是E_FAIL

#include <Windows.h>
#import <finalconstructtest.dll>

int main()
{
    HRESULT hr = CoInitialize(0);
    {
        finalconstructtestLib::IFCClassPtr p;

        // Returns REGDB_E_CLASSNOTREG
        hr = p.CreateInstance(__uuidof(finalconstructtestLib::FCClass));         
    }
    CoUninitialize();
    return 0;
}

但是,当我将类上下文更改为CLSCTX_INPROC_SERVER时,会正确返回所需的HRESULT:

// Returns E_FAIL
hr = p.CreateInstance(__uuidof(finalconstructtestLib::FCClass), nullptr, CLSCTX_INPROC_SERVER);

我已经看过this帖子,可以观察到类似的行为。但是,我似乎无法找到类上下文影响FinalConstruct的返回值的任何理由。这是有意的,也许是在某处记录的吗?

1 个答案:

答案 0 :(得分:1)

CoCreateInstance API不承诺将内部失败代码转发给调用者。实现更喜欢以自己的方式指示问题的根源,方法是返回REGDB_E_CLASSNOTREG,意味着它无法完成实例化。反过来也是如此:它确实无法创建实例(例如,问题不在于缺少接口,封送,权限等)。也就是说,API倾向于禁止内部故障代码,以用记录的代码替换它。

如果您希望指出特定的实例化失败,那么最好在初始创建实例时成功,然后您可以实现具有属性或方法的接口,从而暴露状态或提供相关的HRESULT错误(有或没有IErrorInfo支持等。)