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?
I felt the following points are unnerving, so I have addressed them and found a solution that works for me:
GetActiveObject("VisualStudio.DTE.10.0")
only works for the first opened (I suppose) Visual Studiointernal static DTE2 GetCurrent()
method of Dennis' answer needs the Visual Studio process Id. That is fine if you run the code from add-ins (I think), but does not work e.g. in unit tests.I also started out with the GetCurrent method, taken from here. Problem was, I didn't know how to get to the ProcessId of the right VisualStudio process (usually multiple instances are running). So the approach I took was getting all VisualStudio ROT entries and their DTE2, then comparing DTE2.Solution.FullName to the executing assembly location (do you see a better choice?). While I readily admit this is not very exact science, it should work if you do not have rather special Output Path configurations. Then I found that running my code in debug mode and accessing the DTE2 COM objects threw the following exception:
System.Runtime.InteropServices.COMException: Call was rejected by callee. (Exception from HRESULT: 0x80010001 (RPC_E_CALL_REJECTED))
. There is a remedy for that though, called MessageFilter. I have included the code at the bottom for completeness sake.Test class containing a test method (usage example), the adjusted
GetCurrent
method and a helper method for string comparison:MessageFilter class:
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:
And at the point that I want to access the current IDE:
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.
for anyone interested in doing this with F# a mostly complete conversion is here ( currently set to run in linqpad):
I know this is an old thread, but we needed to use this code with multiple Visual Studio versions. We tweaked the code as below:
I've made the perfect solution below a bit more comfortabel (no Rocket Science). This one works it's way down from Visual Studio 20 to 10 to find the DTE independent of VS versions.