COM错误:类未注册(我确定它已经注册了)

4

我有一个非常复杂的程序,存在COM问题。
我试图编写一个更小的SSCCE程序来减少问题。

但是,无论我尝试什么,我的SSCCE中的CoCreateInstance都会返回

hr 0x80040154 (Class Not Registered)  (For CoCreateInstance)
0x800706B5: The interface is unknown. (for ICalendarPtr constructor)

我正在使用来自较大程序的相同GUID和其他参数。
(结果发现我并没有使用相同的GUID,只是类似的)
我链接到相同的库,并且拥有相同的DLL文件(本地和Program Files中都已正确注册)。
我不是一个注册表专家,但浏览注册表后,我发现接口和类GUID看起来已经被正确注册,并且有一个TypeLib键引用了一个存在且可访问的DLL。
您能否想到导致一个程序成功创建COM对象,而另一个程序却说该类未注册的原因?
代码:
_COM_SMARTPTR_TYPEDEF(ICalendar, __uuidof(ICalendar));

int _tmain(int argc, _TCHAR* argv[])
{
    CoInitialize(NULL);

    CLSID classID = __uuidof(ICalendar);
    REFIID iid = __uuidof(IUnknown);
    LPVOID pRet;
    HRESULT hr = CoCreateInstance(classID, NULL, CLSCTX_INPROC_SERVER, iid, &pRet);
    // Result: 0x80040154 Class not registered

    GUID guid = __uuidof(ICalendar);
    ICalendarPtr pDtTm(guid);
    // Result: First-chance exception at 0x773dc41f in COMTest.exe: 0x800706B5: The interface is unknown.


    return 0;
}

同样的架构?(32/64位)?您可以始终检查注册表以查看是否已正确注册。 - WhozCraig
是的,同一台物理计算机。在两种情况下都使用了“/MACHINE:X86”进行编译。我查看注册表似乎表明它已经注册。 - abelenky
哎呀,这两个都错了。你传递的是接口的 UUID,而不是 CoClass 的 UUID。你需要使用 CLSID_Calendar,或者你正在创建的对象的 CoClass ID。如果头文件可用,请使用 __uuidof(Calendar) 或者实际上公开该接口的 CoClass 名称。打开头文件并查找 coclass,你会找到它的。 - WhozCraig
糟糕!工作中的程序有 ICalendarPtr pDtTm(__uuidof(Calendar)); 但我把 ICalendarPtr pDtTm(__uuidof(ICalendar)); 复制到了我的程序中。谢谢! - abelenky
1
Lebeau先生已经拥有了它。不用担心。 - WhozCraig
1个回答

10

CLSID classID = __uuidof(Calendar);

这是错误的。 __uuidof() 检索接口的 IID,而不是它的 CLSID。 在调用 CoCreateInstance() 时,您需要在第一个参数中使用 CLSID,在第四个参数中使用 IID,例如:

ICalendar *pRet;
HRESULT hr = CoCreateInstance(CLSID_Calendar, NULL, CLSCTX_INPROC_SERVER, __uuidof(ICalendar), (void**)&pRet);

使用接口智能封装器的构造函数时,需要使用CLSID,例如:
ICalendarPtr pDtTm(CLSID_Calendar);

没有编译器语法可以检索接口的CLSID。您需要导入接口的类型库,然后使用生成的.h文件获取定义,或者在运行时执行注册表查找,例如使用 CLSIDFromProgID()


1
+1 感谢您为我节省了击键次数。我仍然感到羞愧,第一次扫描源代码时错过了它。 - WhozCraig
@WhozCraig: 我给你在其他答案上点了赞,以表扬你的声望分数。 :) - abelenky
1
@abelenky,虽然我很感激,但我不建议你这样做。如果你遇到了一个对你正在做的事情或感兴趣的事情有帮助的答案,那么请随意使用,但不要只是为了堆积分数。 - WhozCraig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接