2016-05-31 20 views
0

Ich habe ein ATL-Projekt, wo ich verschiedene Initialisierungsroutinen innerhalb CComObjectRootEx::FinalConstruct ausführen muss. Zu Demonstrationszwecken betrachten wir die folgende Umsetzung:_com_ptr_t CreateInstance gibt REGDB_E_CLASSNOTREG zurück

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

Dies sollte die entsprechende HRESULT an den Aufrufer zurückgeben, der angibt, ob die Initialisierung des Objekts erfolgreich war.

jedoch immer der Kunde erhält REGDB_E_CLASSNOTREG statt E_FAIL im Fall des Scheiterns, wenn man versucht, den Server zu erstellen:

#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; 
} 

Wenn ich den Klassenkontext zu CLSCTX_INPROC_SERVER jedoch ändern, die beabsichtigten HRESULT korrekt zurückgegeben:

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

ich habe this Post gesehen, wo ein ähnliches Verhalten beobachtet werden kann. Ich kann jedoch keinen Grund finden, warum der Klassenkontext den Rückgabewert von FinalConstruct beeinflusst. Ist das beabsichtigt und vielleicht irgendwo dokumentiert?

Antwort

1

CoCreateInstance API verspricht nicht, den internen Fehlercode an den Aufrufer weiterzuleiten. Die Implementierung zeigt die Quelle des Problems vorzugsweise auf ihre eigene Weise an, indem sie REGDB_E_CLASSNOTREG zurückgibt, was bedeutet, dass sie die Instanziierung nicht abschließen konnte. Was wiederum wahr ist: Es war tatsächlich nicht möglich, eine Instanz zu erstellen (und das Problem bezieht sich beispielsweise nicht auf fehlende Schnittstellen, Marshalling, Berechtigungen usw.). Das heißt, die API unterdrückt lieber internen Fehlercode, um ihn durch einen dokumentierten Fehlercode zu ersetzen.

Wenn Sie es vorziehen, einen bestimmten Instanziierungsfehler anzugeben, ist es besser, eine Instanz initial zu erstellen und dann eine Schnittstelle mit einer Eigenschaft oder Methode zu implementieren, die den Status ausgibt, oder einen entsprechenden HRESULT Fehler (mit oder ohne IErrorInfo Unterstützung usw.).