以编程方式从addins获取当前的Visual Studio IDE解决方案目录

我有一些工具可以在.NET解决方案上执行更新,但是他们需要知道解决方案所在的目录。

我将这些工具添加为外部工具,它们出现在IDE工具菜单中,并提供$(SolutionDir)作为参数。 这很好用。

但是,我希望通过自定义顶级菜单(我为其创建Visual Studio集成包项目)以及通过解决方案节点上的上下文菜单(我为其创建了一个Visual),在IDE中为用户更轻松地访问这些工具。 Studio加载项目)。 我正在寻找一种方法来通过这些上下文获取当前的解决方案目录。

我尝试从VisualStudio.DTE对象获取解决方案信息:

 EnvDTE.DTE dte = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE"); string solutionDir = System.IO.Path.GetDirectoryName(dte.Solution.FullName); 

但是,这将返回add ins的解决方案目录,而不是当前解决方案。

我尝试回显$(SolutionDir)并将其读回:

 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(); 

但是,这返回了IDE的目录,而不是当前的解决方案。

我没有在解决方案节点CommandBar看到任何相关信息。

或者,如果有一种方法可以以编程方式访问已定义的Visual Studio外部工具并启动它们(使用已定义的宏参数),那么这将起作用。

解决办法是什么?

EnvDTE.DTE dte =(EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject(“VisualStudio.DTE”); string solutionDir = System.IO.Path.GetDirectoryName(dte.Solution.FullName);

但是,这将返回add ins的解决方案目录,而不是当前解决方案。

您获取目录的方法很好。 你得到VisualStudio.DTE对象的方式有什么不对。 这段代码在哪里叫? 我认为它在你的加载项中。 您是否在Visual Studio中执行(调试)您的加载项,打开另一个Visual Studio实例来打开您的解决方案? 所以你有两个Visual Studio实例。

GetActiveObject("VisualStudio.DTE")获取一个随机的Visual Studio实例。 在您的情况下,它显然是带有加载项项目的Visual Studio,因为您可以获得加载项的路径。 这是为了解释你的问题的原因。

获得DTE的正确方法非常简单。 实际上,您的加载项已经引用了运行它的DTE(即打开解决方案的DTE)。 它存储在加载项连接类的全局变量_applicationObject中。 当您的加载项在OnConnection事件处理程序中启动时设置它。 所以你需要的是打电话:

 string solutionDir = System.IO.Path.GetDirectoryName(_applicationObject.Solution.FullName); 

随着Peter向正确的方向推进,我设置了上下文菜单插件以启动带有解决方案目录的外部工具,并将结果输出到输出窗格。 添加的一些示例模糊:

  ///-------------------------------------------------------------------------------- /// This method implements the OnConnection method of the IDTExtensibility2 interface. Receives notification that the Add-in is being loaded. /// /// Root object of the host application. /// Describes how the Add-in is being loaded. /// Object representing this Add-in. ///  ///-------------------------------------------------------------------------------- public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom) { _applicationObject = (DTE2)application; _addInInstance = (AddIn)addInInst; // Get the solution command bar CommandBar solutionCommandBar = ((CommandBars)_applicationObject.CommandBars)["Solution"]; // Set up the main InCode CommandBarPopup solutionPopup = (CommandBarPopup)solutionCommandBar.Controls.Add(MsoControlType.msoControlPopup, System.Reflection.Missing.Value, System.Reflection.Missing.Value, 1, true); solutionPopup.Caption = "InCode"; // Add solution updater submenu CommandBarControl solutionUpdaterControl = solutionPopup.Controls.Add(MsoControlType.msoControlButton, System.Reflection.Missing.Value, System.Reflection.Missing.Value, 1, true); solutionUpdaterControl.Caption = "Update Solution"; updateSolutionMenuItemHandler = (CommandBarEvents)_applicationObject.Events.get_CommandBarEvents(solutionUpdaterControl); updateSolutionMenuItemHandler.Click += new _dispCommandBarControlEvents_ClickEventHandler(updateSolution_Click); } // The event handlers for the solution submenu items CommandBarEvents updateSolutionMenuItemHandler; ///-------------------------------------------------------------------------------- /// This property gets the solution updater output pane. ///-------------------------------------------------------------------------------- protected OutputWindowPane _solutionUpdaterPane = null; protected OutputWindowPane SolutionUpdaterPane { get { if (_solutionUpdaterPane == null) { OutputWindow outputWindow = _applicationObject.ToolWindows.OutputWindow; foreach (OutputWindowPane loopPane in outputWindow.OutputWindowPanes) { if (loopPane.Name == "Solution Updater") { _solutionUpdaterPane = loopPane; return _solutionUpdaterPane; } } _solutionUpdaterPane = outputWindow.OutputWindowPanes.Add("Solution Updater"); } return _solutionUpdaterPane; } } ///-------------------------------------------------------------------------------- /// This method handles clicking on the Update Solution submenu. /// /// The control that is source of the click. /// Handled flag. /// Cancel default flag. ///-------------------------------------------------------------------------------- protected void updateSolution_Click(object inputCommandBarControl, ref bool handled, ref bool cancelDefault) { try { // set up and execute solution updater thread UpdateSolutionDelegate updateSolutionDelegate = UpdateSolution; updateSolutionDelegate.BeginInvoke(UpdateSolutionCompleted, updateSolutionDelegate); } catch (System.Exception ex) { // put exception message in output pane SolutionUpdaterPane.OutputString(ex.Message); } } protected delegate void UpdateSolutionDelegate(); ///-------------------------------------------------------------------------------- /// This method launches the solution updater to update the solution. ///-------------------------------------------------------------------------------- protected void UpdateSolution() { try { // set up solution updater process string solutionDir = System.IO.Path.GetDirectoryName(_applicationObject.Solution.FullName); System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo(@"SolutionUpdater.exe", solutionDir); procStartInfo.RedirectStandardOutput = true; procStartInfo.UseShellExecute = false; procStartInfo.CreateNoWindow = true; System.Diagnostics.Process proc = new System.Diagnostics.Process(); proc.StartInfo = procStartInfo; // execute the solution updater proc.Start(); // put solution updater output to output pane SolutionUpdaterPane.OutputString(proc.StandardOutput.ReadToEnd()); SolutionUpdaterPane.OutputString("Solution update complete."); } catch (System.Exception ex) { // put exception message in output pane SolutionUpdaterPane.OutputString(ex.Message); } } ///-------------------------------------------------------------------------------- /// This method completing the update solution thread. /// /// IAsyncResult. ///-------------------------------------------------------------------------------- protected void UpdateSolutionCompleted(IAsyncResult ar) { try { if (ar == null) throw new ArgumentNullException("ar"); UpdateSolutionDelegate updateSolutionDelegate = ar.AsyncState as UpdateSolutionDelegate; Trace.Assert(updateSolutionDelegate != null, "Invalid object type"); updateSolutionDelegate.EndInvoke(ar); } catch (System.Exception ex) { // put exception message in output pane SolutionUpdaterPane.OutputString(ex.Message); } }