2009-05-19 5 views
1

Dies ist etwas verwandt mit another question that I've asked, dass ich ziemlich viel herausgefunden habe. Das letzte Puzzleteil verwendet CoCreateInstance() anstelle von GetActiveObject(). Ich möchte keine vorhandene Instanz von EnvDTE verwenden, daher rufe ich CoCreateInstance auf, wodurch eine neue Instanz von VisualStudio ordnungsgemäß ausgelöst wird. CoCreateInstance() ruft AddRef() auf, und ich speichere den Ausgabezeiger in einem CComPtr, der Freigabe bei Zerstörung ordnungsgemäß aufruft. Wenn dieses Release() passiert, wird die Instanz von VS geschlossen! Natürlich, weil der Refcount auf Null steht. Was ich tun möchte, ist, dass der neue Prozess die letzte Instanz besitzt. Wenn also der Benutzer VS mit der Schaltfläche Schließen (X) schließt, zerstört er das COM-Objekt.CoCreateInstance für EnvDTE ohne AddRef()?

Es gibt ein paar Dinge, die ich versucht habe: 1. Aufruf Detach() auf meinem CComPtr, so dass das Objekt weiterlebt. Sicher, es funktioniert jedoch, schließen VS mit der Schließen-Schaltfläche nicht wirklich den Prozess (es läuft immer noch in der Task-Manager-Liste). 2. Starten Sie einen separaten Prozess von VS und verwenden Sie dann ROT, um die neue Instanz zu finden. Das ist hässlich, weil ich eine unbestimmte Zeit warten muss, bis die Anwendung gestartet wird, bevor ich versuche, die neue Instanz des COM-Objekts zu finden. 3. Verwenden Sie ein globales oder statisches CComPtr und zerstören Sie das Objekt manuell, wenn meine App geschlossen wird. Ich würde es lieber nicht so machen.

Antwort

1

Also habe ich das für den spezifischen Fall des Erstellen eines VisualStudio.DTE-Objekts mit CoCreateInstance herausgefunden. Das zurückgegebene DTE-Objekt verfügt über eine UserControl-Eigenschaft, die auf TRUE festgelegt werden kann. Wenn Sie dies auf TRUE setzen, zerstört ein Release() des CComPtr, das das DTE-Objekt enthält, die Instanz nicht:

#define RETURN_ON_FAIL(expression) \ 
result = (expression); \ 
if (FAILED(result))  \ 
    return false;   \ 
else // To prevent danging else condition 

HRESULT result; 
CLSID clsid; 
CComPtr<IUnknown> punk = NULL; 

CComPtr<EnvDTE::_DTE> dte = NULL; 
RETURN_ON_FAIL(::CLSIDFromProgID(L"VisualStudio.DTE", &clsid)); 
RETURN_ON_FAIL(::CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, EnvDTE::IID__DTE, (LPVOID*)&punk)); 
dte = punk; 
dte->put_UserControl(TRUE); 
0

Betrachten Sie WindowClosing Event. Sie können dieses Ereignis abonnieren und wenn das Ereignis ausgelöst wird, rufen Sie Release() auf. Dazu müssen Sie festlegen, welche Fensterereignisse abonniert werden sollen.

Verwandte Themen