Laufende Visual Studio Instanz filtern
Frank Dzaebel, erstellt am: 4.04.2007, zuletzt geändert: 9.04.2007
Kategorie:Implementation, .NET-Version:2.0

Das Problem, dass ein  GetActiveObject("VisualStudio.DTE") nur die zuerst erstellte (registrierte) Visual Studio Instanz darstellt, kann man durch eine Durchsuchung des ROT (Running Object Table), nach einer Instanz, dessen Prozess-ID am Ende des "runningObjectName" steht und dessen ProgID vorneweg steht, lösen.

Getestet auf [Visual Studio 2005, Visual Studio Codename Orcas März CTP 2007]

Weiterführende Literatur:
Automating a specific instance of Visual Studio .NET using C#
Get running Visual Studio instances and corresponding _DTE objects


using System;
using System.Runtime.InteropServices.ComTypes;
using System.Runtime.InteropServices;
using System.Diagnostics;

class VStudio
{
  [DllImport("ole32.dll")]
  static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot);

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

  /// <summary>Rückgabe: Die Instanz des aktuellen Prozesses aller laufenden Instanzen 
  /// der ProgID, die momentan im Running Object Table (ROT) sind. </summary>
  static object ROT_Instanz(string progID)
  {
    IntPtr numFetched = IntPtr.Zero;
    IRunningObjectTable runningObjectTable;
    IEnumMoniker monikerEnumerator;
    IMoniker[] monikers = new IMoniker[1];

    GetRunningObjectTable(0, out runningObjectTable);
    runningObjectTable.EnumRunning(out monikerEnumerator);
    monikerEnumerator.Reset(); string progIDValue = "!" + progID;
    while (monikerEnumerator.Next(1, monikers, numFetched) == 0)
    {
      IBindCtx ctx; CreateBindCtx(0, out ctx);
      string runningObjectName;
      monikers[0].GetDisplayName(ctx, null, out runningObjectName);
      if (!runningObjectName.StartsWith(progIDValue)) continue;
      string procID = ":"+Process.GetCurrentProcess().Id.ToString();
      object runningObjectVal;
      if (!runningObjectName.EndsWith(procID)) continue;
      runningObjectTable.GetObject(monikers[0], out runningObjectVal);
      return runningObjectVal;
    }
    return null;
  }

  /// <summary>Visual-Studio-Instanz (EnvDTE.DTE).</summary>
  static public EnvDTE.DTE Instanz()
  {
    return ROT_Instanz("VisualStudio.DTE") as EnvDTE.DTE;
  }
}
Aufruf (z.B.) in einem UserControl zur Designzeit:



 EnvDTE.DTE dte = VStudio.Instanz(); MessageBox.Show(dte.ActiveDocument.FullName);