2009-05-18 4 views
0

Ich verwende die EnvDTE COM-Objekte, um Visual Studio zu automatisieren. Ich schaue immer noch durch die Dokumentation, aber ich dachte, ich würde die Frage hier fallen lassen, um zu sehen, ob jemand bereits weiß, wie das geht.Wie öffne ich eine neue Visual Studio-Instanz mit EnvDTE?

Also, das Problem ist, dass, wenn ich das DTE-Objekt und schau, welche Lösung geöffnet ist, muss ich eine andere Instanz von Visual Studio öffnen, wenn die Lösung nicht die ist, die ich erwarte. Ich möchte nicht unbedingt eine andere Lösung über eine vorhandene Instanz von VS laden.

+0

Verwenden Sie EnvDTE in einem Makro oder in einer DLL? Könnte in Betracht ziehen, abhängig von den Umständen ShellExecute oder sogar DDE zu verwenden. –

+0

Ich verwende es nativ aus C++ in einer ausführbaren Datei. Ich möchte nicht unbedingt ShellExecute verwenden, da die Lösung möglicherweise bereits geöffnet ist. Ich kann dies bereits erkennen, indem ich Solution.FullName ansehe. In dem Fall, dass es nicht existiert, möchte ich VS starten und weiterhin über EnvDTE automatisieren. –

+0

ahh - Ich sehe - es kann bereits in einer anderen Instanz von VS geladen werden. Wenn dies ein Add-In oder ein Paket ist, könnten Sie einen IPC (mit Ihren anderen Instanzen) einrichten, sodass Sie wissen, ob eine andere Instanz bereits mit der darin enthaltenen Lösung ausgeführt wird. –

Antwort

2

Also habe ich das selbst herausgefunden. Es stellt sich heraus, dass die RunningObjectTable die Möglichkeit bietet, über alle VS-Instanzen zu iterieren und nach einer mit der von mir erwarteten Lösung zu suchen. Wenn ich keine Instanz, die ich verwenden kann, dann nenne ich CoCreateInstance() einen neuen VS IDE zu starten:

#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; 
CComPtr<EnvDTE::_DTE> dte; 

RETURN_ON_FAIL(::CLSIDFromProgID(L"VisualStudio.DTE", &clsid)); 

...

// Search through the Running Object Table for an instance of Visual Studio 
    // to use that either has the correct solution already open or does not have 
    // any solution open. 
    CComPtr<IRunningObjectTable> ROT; 
    RETURN_ON_FAIL(GetRunningObjectTable(0, &ROT)); 

    CComPtr<IBindCtx> bindCtx; 
    RETURN_ON_FAIL(CreateBindCtx(0, &bindCtx)); 

    CComPtr<IEnumMoniker> enumMoniker; 
    RETURN_ON_FAIL(ROT->EnumRunning(&enumMoniker)); 

    CComPtr<IMoniker> dteMoniker; 
    RETURN_ON_FAIL(CreateClassMoniker(clsid, &dteMoniker)); 

    CComBSTR bstrSolution(solutionPath); 
    CComPtr<IMoniker> moniker; 
    ULONG monikersFetched = 0; 
    while (enumMoniker->Next(1, &moniker, &monikersFetched) == S_OK) 
    { 
     if (moniker->IsEqual(dteMoniker)) 
     { 
      result = ROT->GetObject(moniker, &punk); 
      if (result == S_OK) 
      { 
       dte = punk; 

       if (dte) 
       { 
        CComPtr<EnvDTE::_Solution> solution; 
        RETURN_ON_FAIL(dte->get_Solution(&solution)); 

        VARIANT_BOOL isOpen = FALSE; 
        RETURN_ON_FAIL(solution->get_IsOpen(&isOpen)); 
        if (!isOpen) 
        { 
         RETURN_ON_FAIL(solution->Open(bstrSolution)); 
         break; 
        } 
        else 
        { 
         CComBSTR fullName; 
         RETURN_ON_FAIL(solution->get_FullName(&fullName)); 

         if (fullName == bstrSolution) 
          break; 
        } 
       } 
      } 

      punk = NULL; 
     } 

     moniker = NULL; 
    } 


if (!dte) 
{  
    RETURN_ON_FAIL(::CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, EnvDTE::IID__DTE, (LPVOID*)&punk)); 
    dte = punk; 

    if (!dte) 
     return false; 

    if (solutionPath) 
    { 
     CComPtr<EnvDTE::_Solution> solution; 
     RETURN_ON_FAIL(dte->get_Solution(&solution)); 

     CComBSTR bstrSolution(solutionPath); 
     RETURN_ON_FAIL(solution->Open(bstrSolution)); 
    } 
}