I have some tools that perform updates on .NET solutions, but they need to know the directory where the solution is located.
I added these tools as External Tools, where they appear in the IDE Tools menu, and supplying $(SolutionDir)
as an argument. This works fine.
However, I want these tools to be easier to access in the IDE for the user through a custom top level menu (for which I created a Visual Studio integration package project) and through a context menu on solution nodes (for which I created a Visual Studio add-in project). I'm looking for a way to get the current solution directory through these contexts.
I tried getting the solution information from the VisualStudio.DTE
object:
EnvDTE.DTE dte = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE");
string solutionDir = System.IO.Path.GetDirectoryName(dte.Solution.FullName);
But, this returns the solution directory for the add ins, not the current solution.
I tried echoing $(SolutionDir)
and reading it back:
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "echo $(SolutionDir)");
// The following commands are needed to redirect the standard output.
// This means that it will be redirected to the Process.StandardOutput StreamReader.
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
// Do not create the black window.
procStartInfo.CreateNoWindow = true;
// Now we create a process, assign its ProcessStartInfo and start it
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
// Get the output into a string
string result = proc.StandardOutput.ReadToEnd();
But, this returned the directory for the IDE, not the current solution.
I didn't see any relevant information in the solution node CommandBar
.
Alternatively, if there was a way to programmatically access the defined Visual Studio external tools and launch them (using the already defined macro arguments), that would work.
What is the solution?
EnvDTE.DTE dte = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE"); string solutionDir = System.IO.Path.GetDirectoryName(dte.Solution.FullName);
But, this returns the solution directory for the add ins, not the current solution.
Your approach to get the directory is good. What's wrong is the way you get the VisualStudio.DTE
object. Where is this code called? I assume it is in your add-in. Do you execute (debug) your add-in in Visual Studio which opens another instance of Visual Studio where you open your solution? So you have two instances of Visual Studio.
The GetActiveObject("VisualStudio.DTE")
gets a random Visual Studio instance. In your case, it is apparently Visual Studio with an add-in project since you get path to your add-in. That's for explanation what would be the reason of your problem.
The correct way to get DTE
is very simple. In fact, your add-in already has reference to DTE in which it runs (that is, in which the solution is opened). It is stored in a global variable _applicationObject in your add-in connect class. It is set when your add-in starts in the OnConnection
event handler. So all you need is to call:
string solutionDir = System.IO.Path.GetDirectoryName(_applicationObject.Solution.FullName);