visual valido una studio soluciones solucion seleccione que proyectos proyecto inicio hechos explorador elemento ejemplos definicion crear compilar como abrir c# visual-studio solution envdte vs-extensibility

c# - valido - que es una solucion en visual studio



Obtención programática del directorio actual de la solución IDE de Visual Studio desde complementos (2)

Tengo algunas herramientas que realizan actualizaciones en soluciones .NET, pero necesitan conocer el directorio donde se encuentra la solución.

Agregué estas herramientas como herramientas externas, donde aparecen en el menú de herramientas IDE y suministrando $(SolutionDir) como argumento. Esto funciona bien.

Sin embargo, quiero que estas herramientas sean más fáciles de acceder en el IDE para el usuario a través de un menú de nivel superior personalizado (para el que creé un proyecto de paquete de integración de Visual Studio) y a través de un menú de contexto en los nodos de la solución (para los que creé un Visual Proyecto complemento de estudio). Estoy buscando una manera de obtener el directorio de la solución actual a través de estos contextos.

Intenté obtener la información de la solución del objeto VisualStudio.DTE :

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

Pero, esto devuelve el directorio de soluciones para los complementos, no la solución actual.

Intenté hacer eco de $(SolutionDir) y leerlo de nuevo:

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

Pero, esto devolvió el directorio para el IDE, no la solución actual.

No vi ninguna información relevante en la solución CommandBar nodo.

Alternativamente, si hubiera una manera de acceder mediante programación a las herramientas externas definidas de Visual Studio y lanzarlas (usando los argumentos de macro ya definidos), eso funcionaría.

¿Cuál es la solución?


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

Pero, esto devuelve el directorio de soluciones para los complementos, no la solución actual.

Su enfoque para obtener el directorio es bueno. Lo que está mal es la forma en que obtiene el objeto VisualStudio.DTE . ¿Dónde se llama este código? Supongo que está en tu complemento. ¿Ejecuta (depura) su complemento en Visual Studio que abre otra instancia de Visual Studio donde abre su solución? Así que tienes dos instancias de Visual Studio.

GetActiveObject("VisualStudio.DTE") obtiene una instancia aleatoria de Visual Studio. En su caso, aparentemente es Visual Studio con un proyecto de complemento, ya que obtiene la ruta de acceso a su complemento. Eso es para explicar cuál sería la razón de tu problema.

La forma correcta de obtener DTE es muy simple. De hecho, su complemento ya tiene una referencia al DTE en el que se ejecuta (es decir, en el que se abre la solución). Se almacena en una variable global _applicationObject en su clase de conexión de complemento. Se establece cuando su complemento se inicia en el controlador de eventos OnConnection . Así que todo lo que necesitas es llamar:

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


Con el empuje de Peter en la dirección correcta, configuré el complemento del menú contextual para iniciar una herramienta externa con el directorio de la solución y mostrar los resultados en el panel de resultados. Un ejemplo de propaganda del complemento:

///-------------------------------------------------------------------------------- /// <summary>This method implements the OnConnection method of the IDTExtensibility2 interface. Receives notification that the Add-in is being loaded.</summary> /// /// <param term=''application''>Root object of the host application.</param> /// <param term=''connectMode''>Describes how the Add-in is being loaded.</param> /// <param term=''addInInst''>Object representing this Add-in.</param> /// <seealso class=''IDTExtensibility2'' /> ///-------------------------------------------------------------------------------- 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; ///-------------------------------------------------------------------------------- /// <summary>This property gets the solution updater output pane.</summary> ///-------------------------------------------------------------------------------- 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; } } ///-------------------------------------------------------------------------------- /// <summary>This method handles clicking on the Update Solution submenu.</summary> /// /// <param term=''inputCommandBarControl''>The control that is source of the click.</param> /// <param term=''handled''>Handled flag.</param> /// <param term=''cancelDefault''>Cancel default flag.</param> ///-------------------------------------------------------------------------------- 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(); ///-------------------------------------------------------------------------------- /// <summary>This method launches the solution updater to update the solution.</summary> ///-------------------------------------------------------------------------------- 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); } } ///-------------------------------------------------------------------------------- /// <summary>This method completing the update solution thread.</summary> /// /// <param name="ar">IAsyncResult.</param> ///-------------------------------------------------------------------------------- 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); } }