I am a COM beginner. I have a DLL file that I register using the regsvr32 command. In the COM client, I try to use the CoCreateInstance function, but it doesn't work. This is my code:
IMessageBox *pBox;
hr = CoCreateInstance(
__uuidof(IMessageBox),
NULL,
CLSCTX_INPROC_SERVER,
IID_IUnknown,
(void **)&pBox
);
IMessageBox is the interface which is defined in my DLL file. It implements the IDispatch interface. The result of hr displays the error REGDB_E_CLASSNOTREG. How do I use the CoCreateInstance function?
Instead of __uuidof(IMessageBox) you have to pass the UUID of the class you want to instantiate - i.e. the class you registered previously using regsrv32.
Well, the error tells you what is the problem. The class you are requesting is not registered in the COM registry. It could be that the IID of class that you registered is not the one that you are requesting. Another common failure mode is that you registered a 32 bit DLL and your calling process is 64 bit. Or vice versa.
Related
I have an ATL DLL that I am trying to consume from an ATL Exe. When I try to create an instance of the object in the DLL it fails with an error REGDB_E_CLASSNOTREG. I have checked the registry and I can see the object is registered, both the ProgID as well as the CLSID.
CComPtr<IMyInterface> ptrMyInterface;
ptrMyInterface.CoCreateInstance(L"ProgID", nullptr, CLSCTX_ALL); // Fails
CLSID myClsid;
CLSIDFromString(L"{MyCLSID}"), &myClsid); // Correctly looks up the CLSID
ptrMyInterface.CoCreateInstance(myClsid, nullptr, CLSCTX_ALL); // Also fails
Any suggestions
Ok, I feel really kind of silly. The problem was the fact that CComPtr was trying to call QueryInterface on the object I was CoCreating. The Interface that I was using was not implemented by the class that I was creating. It seems that there would be a better error than REGDB_E_CLASSNOTREG. Something like E_NOINTERFACE would be a better return code IMHO.
CComPtr<IMyCorrectInterface> ptrMyInterface;
ptrMyInterface.CoCreateInstance(L"ProgID", nullptr, CLSCTX_ALL); // WORKS!!!
Now I'm Writing This Code
IFileDialog *pfd = NULL;
HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&pfd));
after Compiling an Error Appeared; "IFileDialog Not Declared in this Scope"
What is The Library of that Class ??
You don't need to know which library implements it. This is a COM interface that you invoke with a call to CoCreateInstance. The system does the rest. It looks up the implementing COM server in the COM registry and instantiates your object.
In order to compile you just need to include Shobjidl.h, and define the version macros appropriately. You need
#define _WINNT_WIN32 0600
I have a large complex program that has a COM problem.
I'm attempting to write a much smaller SSCCE program to reduce the problem.
However, no matter what I try, the CoCreateInstance in my SSCCE keeps coming back with
hr 0x80040154 (Class Not Registered) (For CoCreateInstance)
0x800706B5: The interface is unknown. (for ICalendarPtr constructor)
I'm using the same GUIDs and other parameters from the bigger program.
(turns out I wasn't using the same guids. Just similar ones)
I'm linking to the same libraries, and have the same DLLs available (both locally and properly registered in Program Files).
I'm not a Registry expert, but looking through the registry, I do find the Interface and Class GUID look to be properly registered, with a TypeLib-key that refers to a DLL that is present and accessible.
Can you think of something I might be missing that would cause one program to create a COM object successfully, but another to say the class isn't registered?
Code:
_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;
}
CLSID classID = __uuidof(ICalendar);
This is wrong. __uuidof() retrieves an interface's IID, not its CLSID. When calling CoCreateInstance(), you need to use the CLSID in the 1st parameter and the IID in the 4th parameter, eg:
ICalendar *pRet;
HRESULT hr = CoCreateInstance(CLSID_Calendar, NULL, CLSCTX_INPROC_SERVER, __uuidof(ICalendar), (void**)&pRet);
When using the constructor of an interface smart wrapper, you need to use the CLSID, eg:
ICalendarPtr pDtTm(CLSID_Calendar);
There is no compiler syntax for retrieving an interface's CLSID. You have to import the interface's TypeLibrary and then use the generated .h file to get the definitions, or else do a lookup of the Registry at runtime, such as with CLSIDFromProgID().
I have a C# dll that I properly have registered for COM Interop, and made COM visible. Using cppbuilder, I imported the type library, which generated the wrapper classes, and I am now attempting to use to create an instance of my C# class. However, I'm getting a REGDB_E_CLASSNOTREG error in my C++ code. I verified the dll is in the registry, and even re-registered it with regasm. No change. What could I be missing?
Here is my C++ code:
_MyClassPtr obj;
HRESULT hr = obj.CreateInstance(__uuidof(MyClass));
//now hr equals REGDB_E_CLASSNOTREG
I've also tried it as such:
IMyClass* obj;
HRESULT hr = CoCreateInstance(__uuidof(MyClass), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMyClass), (void**) &obj);
//same result, hr equals REGDB_E_CLASSNOTREG
I do have one additional dependency in the C# app. I registered it for COM as well with no difference, but did not import it's type library into the C++ project.
UPDATE: based on the comments below, I discovered that CreateInstance is looking up the class guid in the following places in the registry:
HKCU\Software\Classes\Wow6432Node\CLSID\{guid}
HKCR\Wow6432Node\CLSID\{guid}
HKCU\Software\Classes\CLSID\{guid}
HKCR\CLSID\{guid}
But, going through the registry, the only entry under any of the CLSID nodes that is related to my assembly is the guid for the assembly itself, which is, of course, different than the guid for the class, or the interface.
I've manually run regasm under both x86 and x64 mode to try to acheive different results. No differences.
Well, I found out what would work.
IMyClassPtr obj;
HRESULT hr = obj.CreateInstance(CLSID_MyClass);
CLSID_MyCLass was a guid constant in the generated MyClass_TLB.cpp file. Using it instead of __uuidof(...) for the class types enabled everything to start working correctly.
I'm trying to port a LabView program to C++, and the OLE calls it contains are giving me some trouble.
The LabView program starts out by doing an "Automation open", i.e. getting a reference to the interface "XLib.XInterface" (LabView calls this expression the "ActiveX class"), then calls the method QA found in the interface and finally closes the reference again. I think LabView gets its info on the interface from the type library, but I'm not entierly sure.
I've tried to adapt some code for Word automation I found: http://www.codeproject.com/KB/office/MSOfficeAuto.aspx
CoInitialize(NULL);
CLSID clsid;
HRESULT hr = CLSIDFromProgID(L"XConfig.XInterface", &clsid);
IDispatch *pWApp;
if(SUCCEEDED(hr))
{
hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER,
IID_IDispatch, (void **)&pWApp);
}
// etc.
The program is successful in looking up the CLSID, but CoCreateInstance fails, claiming that the class is not registered. I've also tried entering the CLSID from the type library directly, bypassing CLSIDFromProgID, but yielding the same result. Needless to say that the LabView program works fine, and the C++ code I'm using has no trouble at all to create an instance of Word when using the progID "Word.Application". The interface in question looks like this:
[
odl,
uuid(33AAA2DA-70EB-48EE-ACA7-DD0D1F5CAF2D),
helpstring("XInterface Interface"),
dual,
oleautomation
]
interface XInterface : IDispatch {
[id(0x00000001), helpstring("method QA")]
HRESULT QA();
[id(0x00000002), helpstring("method LoadFromDisk")]
HRESULT LoadFromDisk();
...
As you may have noticed, OLE is kind of new to me (most likely, that's a part of the problem). Any hints would be greatly appreciated. Thanks.
OK, I think I figured it out by myself, even though I don't fully understand my solution. Anyway, when I use
hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_IDispatch,
(void **)&pWApp);
it seems to work; at least I don't get the "class not registered" error anymore. The difference is replacing the argument CLSCTX_LOCAL_SERVER with CLSCTX_ALL. I think it's got something to do with the fact that I'm using a dll. Does anyone have a more insightful explaination?