2010-01-13 12 views
21

Mam kilka narzędzi, które wykonują aktualizacje rozwiązań .NET, ale muszą znać katalog, w którym znajduje się rozwiązanie.Programowe pobieranie bieżącego katalogu rozwiązania IDE Visual Studio z dodatków

Dodałem te narzędzia jako Narzędzia zewnętrzne, gdzie pojawiają się one w menu Narzędzia IDE i dostarczają $(SolutionDir) jako argument. To działa dobrze.

Jednak chcę, aby te narzędzia były łatwiej dostępne w IDE dla użytkownika poprzez niestandardowe menu najwyższego poziomu (dla którego stworzyłem projekt pakietu integracji Visual Studio) oraz poprzez menu kontekstowe na węzłach rozwiązania (dla których Stworzyłem projekt dodatku Visual Studio). Szukam sposobu, aby uzyskać bieżący katalog rozwiązania przez te konteksty.

próbowałem uzyskiwanie informacji rozwiązanie z obiektu VisualStudio.DTE:

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

Ale to zwraca katalog rozwiązanie dla ins dodawać, a nie obecnego rozwiązania.

Próbowałem echo $(SolutionDir) i czytając go z powrotem:

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

Ale ten powrócił do katalogu dla IDE, a nie obecne rozwiązanie.

Nie widziałem żadnych istotnych informacji w węźle rozwiązania CommandBar.

Alternatywnie, jeśli byłby sposób na programowy dostęp do zdefiniowanych narzędzi zewnętrznych Visual Studio i ich uruchomienie (przy użyciu już zdefiniowanych argumentów makra), to by działało.

Jakie jest rozwiązanie?

+0

2+ ponownie widocznie jestem stalking cię tutaj z tego DTE szaleństwa lol – Terrance

Odpowiedz

18

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

Ale to zwraca katalog rozwiązań dla modułów dodatkowych, a nie bieżące rozwiązanie .

Twoje podejście do uzyskania katalogu jest dobre. Zepsuty jest sposób, w jaki zdobywasz obiekt VisualStudio.DTE. Gdzie jest ten kod? Zakładam, że jest w twoim dodatku. Czy uruchamiasz (debugujesz) swój dodatek w Visual Studio, który otwiera kolejną instancję Visual Studio, w której otwierasz swoje rozwiązanie? Więc masz dwa wystąpienia Visual Studio.

Obiekt otrzymuje losową instancję programu Visual Studio. W twoim przypadku najwyraźniej jest to Visual Studio z projektem dodatkowym, ponieważ dostajesz ścieżkę do swojego dodatku. To jest wyjaśnienie, jaka byłaby przyczyna twojego problemu.

Prawidłowy sposób uzyskania DTE jest bardzo prosty. W rzeczywistości Twój dodatek ma już odniesienie do DTE, w którym działa (to znaczy, w którym rozwiązanie jest otwierane). Jest przechowywany w zmiennej globalnej _applicationObject w Twojej klasie connect-add. Jest on ustawiony, gdy twój dodatek zaczyna się w obsłudze zdarzeń OnConnection.Więc wszystko, co potrzebne jest, aby zadzwonić:

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

Dzięki Peter, który właśnie problem i rozwiązanie! Teraz znajdę sposób, aby uzyskać wyjście z wykonywania narzędzi za pośrednictwem menu niestandardowych, aby przejść do okna wyjściowego zamiast osobnego okna i wszystko będzie działać idealnie. Dzięki jeszcze raz. –

6

push Piotra w dobrym kierunku, skonfigurować tego dodatku menu kontekstowego, aby uruchomić narzędzie zewnętrzne z katalogu rozwiązań, i wysyłają wyniki do panelu wyjściowego. Niektóre przykład krótką informację od dodatku w:

///-------------------------------------------------------------------------------- 
    /// <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

Nie, nie znalazłem sposobu na sondowanie zewnętrznego procesu, skończyło się na zrobieniu tego, czego potrzebowałem jako wewnętrznego procesu w Pakiecie VS. –

+0

Mam rozwiązanie do odpytywania wyników (lub raczej przesyłania strumienia wyjściowego do panelu wyjściowego), przynajmniej przy użyciu VSPackage. Raczej poza zakresem tego pytania (i nie pasuje tutaj ..), więc być może możesz otworzyć nowe pytanie, a ja tam odpowiem. –

+0

OK, wyrzuciłem osobne pytanie na ten temat, jeśli twoja odpowiedź wygląda dobrze, zaakceptuję! http://stackoverflow.com/questions/8345636/is-there-a-good-way-to-stream-the-results- from-an-external-process-into-a-visual –

Powiązane problemy