tags:

views:

573

answers:

4

Hi

From some old c++ code im trying to use a com dll, it works fine when the dll is registered, but it crahses if the dll isnt registered.

// Initialize COM. HRESULT hr = CoInitialize(NULL);

IGetTestPtr ptest(__uuidof(tester));

"Use method from the dll"

// Uninitialize COM. CoUninitialize();

Is it anyway to check if the dll has been registered, before calling IGetTestPtr ptest(__uuidof(tester))?

Or what is the correct way to prevent the crash?

+2  A: 

If the DLL is registered, there is a record in HKCR/CLSID/{uuidof(tester)} (curly brackets do matter).

Actually, if it's not, then CoCreateInstance will return an error. Check for this error before using the pointer.

Quassnoi
Don't depend on the internal implementations i.e., registry keys. Microsoft can change at any time.
Vinay
+2  A: 

Calling CreateInstance on your object will return an HRESULT that can be tested for success:

IGetTestPtr p = null; 
HRESULT hRes = p.CreateInstance( __uuidof(tester) );
bool bSuccess = SUCCEEDED(hRes);

This assumes you've created an interface wrapper around your type library using Visual Studio, where COM Smart Pointers are used in the interface (this gives you the CreateInstance method).

Robin M
You are confusing .Net's COM interop with native C++ COM. Which object do you suppose implements the CreateInstance method?
Stu Mackellar
@Stu - I loosely based this on code I wrote a while ago in an C++ MFC app calling a C++ COM object. I don't think I'm confusing .NET interop but it's conceivable that I'm confusing C++ frameworks. I'll look into it further and update my answer.
Robin M
This answer and the OP question are both using the Microsoft compiler's support for COM. It is not MFC or ATL (or the direct SDK), but YET ANOTHER way to use COM from VC++. You know you're using it when you see the #import preprocessor directive.This is NOT .NET!
Aardvark
@Aardvark - yes, I agree. See my update to my answer.
Robin M
I personally hate this framework, it's redundant with other COM frameworks, hides important details, and makes some odd-looking code (properties?? WTF??). Just give me CoCreateInstance please...
Aardvark
Ok - I stand corrected. It seems to be just creating smart pointer wrappers around the imported interfaces. What if you don't have a type library to import?
Stu Mackellar
+2  A: 

If the COM class is not registered then CoCreateInstance will return REGDB_E_CLASSNOTREG. You should check for general success or failure by using the SUCCEEDED() or FAILED() macros. You also need to create the object properly - see MDSN for an introduction to COM. For example:

HRESULT hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
    IGetTestPtr ptr = NULL;
    hr = CoCreateInstance(CLSID_MyObjectNULL, CLSCTX_INPROC_SERVER, IID_IMyInterface, ptr)
    if (SUCCEEDED(hr))
    {
        Do something with your COM object
        ...

        // Don't forget to release your interface pointer or the object will leak
        ptr->Release();
    }

    hr = CoUninitialize();
}
return hr;
Stu Mackellar
A: 

If I recall correctly this "#import" styled COM framework throws exceptions. Add a try-catch block around the code. Google tells me the exceptions are of type _com_error.

Unless you twiddle the params on #import to prevent this, all failing COM calls are going to throw exceptions. You're going to have to turn this off (#import "raw" interfaces I think does it - look at the #import docs) or get real familiar with these exceptions.

Aardvark