Anbindung an eine bestehende Visual Studio-Instanz

Die folgenden Code-Ausschnitte zeigen, wie die Anbindung an eine bestehende (bereits laufende) Instanz von Visual Studio vorgenommen wird. Die Ausschnitte wurden in C# geschrieben.

Das Beispiel setzt sich aus drei verschiedenen Methoden zusammen, die voneinander abhängig sind. Selbstverständlich können Sie Anpassungen vornehmen, damit es besser zu Ihrer Anwendungsumgebung passt. Die folgende Tabelle erläutert jede Methode im Einzelnen.

Methode

Beschreibung

getRunningObjectTable()

Befragt die Running Object Table (ROT) nach einem Snapshot aller laufenden Prozesse in der Tabelle. Gibt alle gefundenen Prozesse in eine Hash-Tabelle zurück, die anschließend von getIdeInstances() zur weiteren Filterung im Hinblick auf DTE-Instanzen verwendet wird.

getIdeInstances()

Sucht nach DTE-Instanzen in dem ROT-Snapshot und gibt eine Hash-Tabelle mit allen gefunden Instanzen zurück. Diese Hash-Tabelle kann dann von der attachToExistingDte()-Methode zwecks Auswahl einzelner DTE-Instanzen verwendet werden.
Sie können die Abfrage für candidateName entsprechend einer spezifischeren Visual Studio progId ändern, z.B. "VisualStudio.DTE.11.0" um nach Visual Studio 2012-Instanzen zu suchen.

attachToExistingDte()

Verwendet die getIdeInstances()-Methode um auf der Grundlage ihres Lösungspfads eine DTE-Instanz zu wählen und, wenn gefunden, ein neues DTE-Objekt an diese Instanz anzubinden.

getRunningObjectTable()

public static Hashtable GetRunningObjectTable() 
{
Hashtable result = new Hashtable();
int numFetched;
UCOMIRunningObjectTable runningObjectTable;
UCOMIEnumMoniker monikerEnumerator;
UCOMIMoniker[] monikers = new UCOMIMoniker[1];
GetRunningObjectTable(0, out runningObjectTable);
runningObjectTable.EnumRunning(out monikerEnumerator);
monikerEnumerator.Reset();
while (monikerEnumerator.Next(1, monikers, out numFetched) == 0)
{
UCOMIBindCtx ctx;
CreateBindCtx(0, out ctx);
string runningObjectName;
monikers[0].GetDisplayName(ctx, null, out runningObjectName);
object runningObjectVal;
runningObjectTable.GetObject(monikers[0], out runningObjectVal);
result[runningObjectName] = runningObjectVal;
}
return result;
}

Bitte achten Sie darauf, dass Sie die CreateBindCtx() Methode als einen DllImport von der ole32.dll ausdrücklich referenzieren müssen, z. B.:

[DllImport("ole32.dll")]
private static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc);

getIdeInstances()

public static Hashtable GetIDEInstances(bool openSolutionsOnly, string progId)
{
    Hashtable runningIDEInstances = new Hashtable();
    Hashtable runningObjects = GetRunningObjectTable();
    IDictionaryEnumerator rotEnumerator = runningObjects.GetEnumerator();
    while (rotEnumerator.MoveNext())
    {
        string candidateName = (string)rotEnumerator.Key;
        if (!candidateName.StartsWith("!" + progId))
        continue;
        EnvDTE.DTE ide = rotEnumerator.Value as EnvDTE.DTE;
        if (ide == null)
        continue;
        if (openSolutionsOnly)
        {
            try
            {
                string solutionFile = ide.Solution.FullName;
                if (solutionFile != String.Empty)
                runningIDEInstances[candidateName] = ide;
            }
            catch { }
         }
         else
            runningIDEInstances[candidateName] = ide;
    }
    return runningIDEInstances;
}

attachToExistingDte()

public EnvDTE.DTE attachToExistingDte(string solutionPath) 
{
EnvDTE.DTE dte = null;
Hashtable dteInstances = GetIDEInstances(false, progId);
IDictionaryEnumerator hashtableEnumerator = dteInstances.GetEnumerator();

while (hashtableEnumerator.MoveNext())
{
EnvDTE.DTE dteTemp = hashtableEnumerator.Value as EnvDTE.DTE;
if (dteTemp.Solution.FullName == solutionPath)
{
Console.WriteLine("Found solution in list of all open DTE objects. " + dteTemp.Name); dte = dteTemp;
}
}
return dte;
}