Get the reference of the DTE2 object in Visual C# 2010

Dennis picture Dennis · Jan 18, 2011 · Viewed 9.3k times · Source

I want to get a reference to the current solution, using the DTE2 object with C# in Visual Studio 2010.

I first tried the following code:

var dte = Marshal.GetActiveObject("VisualStudio.DTE.10.0") as EnvDTE80.DTE2;

But when I open 2 solutions, and this code is in the first solution, I get NOT a reference to the current solution, but a reference to the last solution I loaded. I need the current solution...

Searching on the internet, I found the following solution in How do you get the current solution directory from a VSPackage?:

// Get an instance of the currently running Visual Studio IDE
DTE dte = (DTE)GetService(typeof(DTE));

But when I use this, my dte object is always NULL.

So how do I get to my current solution object in VS2010 using C# on .net framework 4.0?

Answer

Dennis picture Dennis · Jan 18, 2011

After some extensive searching and trying i finally got the answer using the comment that was added to the MSDN page: http://msdn.microsoft.com/en-us/library/ms228755.aspx

I added a static class to my c# project:

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

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

  internal static DTE2 GetCurrent()
  {

     //rot entry for visual studio running under current process.
     string rotEntry = String.Format("!VisualStudio.DTE.10.0:{0}", Process.GetCurrentProcess().Id);
     IRunningObjectTable rot;
     GetRunningObjectTable(0, out rot);
     IEnumMoniker enumMoniker;
     rot.EnumRunning(out enumMoniker);
     enumMoniker.Reset();
     IntPtr fetched = IntPtr.Zero;
     IMoniker[] moniker = new IMoniker[1];
     while (enumMoniker.Next(1, moniker, fetched) == 0)
     {
        IBindCtx bindCtx;
        CreateBindCtx(0, out bindCtx);
        string displayName;
        moniker[0].GetDisplayName(bindCtx, null, out displayName);
        if (displayName == rotEntry)
        {
           object comObject;
           rot.GetObject(moniker[0], out comObject);
           return (EnvDTE80.DTE2)comObject;
        }
     }
     return null;
  }

And at the point that I want to access the current IDE:

var dte = CurrentIde.GetCurrent();
var sol = dte.Solution;

But remember.... This code will NOT work during debugging!!! The line of code starting with string rotEntry... has a call to the Process.GetCurrentProcess to get the ID of the current process.

While debugging some functionality in my addin (using MME http://mme.codeplex.com/) I call a method that needs the current IDE. I test this with a ConsoleApp that calls the addin method. At the point of getting the current IDE, the currentprocess is NOT the IDE, but the ConsoleApp.vshost.exe. So my code did not work during debugging, but DID work after building the addin and installing this addin.