2010-01-13 10 views
21

Ho alcuni strumenti che eseguono gli aggiornamenti sulle soluzioni .NET, ma hanno bisogno di conoscere la directory in cui si trova la soluzione.programmazione ottenere la directory di soluzione di IDE di Visual Studio corrente addins

Ho aggiunto questi strumenti come Strumenti esterni, dove vengono visualizzati nel menu Strumenti IDE e fornendo $(SolutionDir) come argomento. Funziona bene

Tuttavia, desidero che questi strumenti siano più facili da accedere nell'IDE per l'utente tramite un menu personalizzato di livello superiore (per il quale ho creato un progetto di pacchetto di integrazione di Visual Studio) e un menu di scelta rapida sui nodi soluzione (per i quali Ho creato un progetto aggiuntivo di Visual Studio). Sto cercando un modo per ottenere la directory della soluzione corrente attraverso questi contesti.

ho cercato di ottenere le informazioni soluzione dall'oggetto VisualStudio.DTE:

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

Ma, questo restituisce la directory di soluzione per i componenti aggiuntivi, non la soluzione attuale.

ho cercato eco $(SolutionDir) e la lettura indietro:

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

Ma, questo è tornato la directory per l'IDE, non è la soluzione attuale.

non ho visto tutte le informazioni pertinenti nel nodo soluzione CommandBar.

In alternativa, se ci fosse un modo per accedere a livello di codice gli strumenti esterni di Visual Studio definiti e lanciarli (utilizzando gli argomenti di macro già definite), che avrebbe funzionato.

Qual è la soluzione?

+0

2+ di nuovo a quanto pare ti sto inseguendo qui Con questo DTE follia lol – Terrance

risposta

18

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

Tuttavia, questo restituisce la directory della soluzione per i componenti aggiuntivi, non la soluzione corrente .

L'approccio per ottenere la directory è buono. Ciò che è sbagliato è il modo in cui ottieni l'oggetto VisualStudio.DTE. Dove viene chiamato questo codice? Presumo che sia nel tuo componente aggiuntivo. Esegui (fai il debug) il tuo componente aggiuntivo in Visual Studio che apre un'altra istanza di Visual Studio in cui apri la tua soluzione? Quindi hai due istanze di Visual Studio.

Il GetActiveObject("VisualStudio.DTE") ottiene un casuale istanza di Visual Studio. Nel tuo caso, è apparentemente Visual Studio con un progetto aggiuntivo poiché ottieni il percorso per il componente aggiuntivo. Questo è per la spiegazione quale sarebbe la ragione del tuo problema.

Il modo corretto per ottenere DTE è molto semplice. In effetti, il componente aggiuntivo ha già riferimento a DTE in cui viene eseguito (ovvero, in cui viene aperta la soluzione). È memorizzato in una variabile globale _applicationObject nella classe di connessione del componente aggiuntivo. Viene impostato all'avvio del componente aggiuntivo nel gestore eventi OnConnection.Quindi tutto quello che serve è quello di chiamare:

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

Grazie Peter, che era proprio il problema e la soluzione! Ora cercherò un modo per ottenere l'output dall'esecuzione degli strumenti tramite i menu personalizzati per andare alla finestra di output invece di una finestra separata e tutto funzionerà perfettamente. Grazie ancora. –

6

Con spinta di Peter nella direzione giusta, ho creato il componente aggiuntivo menu di scelta rapida per lanciare uno strumento esterno con la directory soluzione e in uscita i risultati nel riquadro di output. Qualche esempio Blurb dal aggiuntivo in:

///-------------------------------------------------------------------------------- 
    /// <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); 
     } 
    } 
+0

No, non ho trovato un modo per eseguire il polling di un processo esterno, ho finito per fare ciò che mi serviva come processo interno in un pacchetto VS. –

+0

Ho una soluzione per il polling dei risultati (o piuttosto lo streaming dell'output nel riquadro di output), almeno quando si utilizza un VSPackage. Piuttosto fuori dagli obiettivi di questa domanda (e non andrà bene qui ..), quindi forse puoi aprire una nuova domanda e ti risponderò. –

+0

OK, ho buttato insieme una domanda a parte per questo, se la tua risposta sembra buona, accetterò! http://stackoverflow.com/questions/8345636/is-there-a-good-way-to-stream-the-results-from-an-external-process-into-a-visual –

Problemi correlati