tags:

views:

611

answers:

4

Consider this code:

try {
    ISomeObject pObj(__uuidof(SomeClass));
    ISomeObject pObj2(__uuidof(SomeOtherClass));
} catch ( _com_error& e ) {
    // Log what failed
}

I.e. I have a block of code which instanciates my objects. Sometimes (a bad install) it failes because some class wasn't properly registered. (I don't have a particular problem, rather general discussion here.)

Is there some way to, from the caught exception or otherwise, realize what class failed? A have pondered to make a wrapper of my own which stores a variable like gLastCreateAttemptUuid, but it feel cumbersome.

Also, suppose that SomeClass in turn attempt to instanciate something else, which isn't registered. Can one then figure out the underlying issue?

A: 

try to check registered classes with this tool,link text

ArsenMkrt
A: 

It's the duty of CoCreateInstance() caller to provide enough information about what it was trying to instantiate - both ATL and Native COM Support have no built-in features for that.

Instead of calling a smart pointer constructor parameterized with a class id you can call its CreateInstance() method - it has exactly the same set of parameters but doesn't throw exceptions. Then you could check the HRESULT and handle the error and provide the class id you just used to the error handler.

However it will not help ypu if the problem happens in the code you don't control. In extreme cases you can use Process Monitor to monitor registry queries and detect which class id is causing the problem.

sharptooth
A: 
crashmstr
The fact that _com_error is being caught means that the OP is not using ATL, but instead using the "builtin COM support" (_com_ptr_t) if I remember right.
Chris Jester-Young
A: 

I have often used my own CoCreateInstance() function wrapper so that if the call fails I can then try and lookup the ProgID from the registry using the CLSID. This way I can at least put the CLSID into the exception string, but hope to do better. I also do this for interfaces as the default string for an interface IID in the registry is often a human readable name. Look at ::StringFromGUID2() for formatting GUIDs.

Of course this does not help you deal with 3rd party dependencies in any way. For this I would go with sharptooth's suggestion of ProcessMonitor (or it's older cousin RegMon).

Chris Oldwood