2009-07-07 10 views
27

Piszę niestandardowe narzędzie i obecnie mam to, co chcę, jeśli chodzi o funkcjonalność. Chciałbym móc napisać do Visual Studio, jeśli coś pójdzie nie tak. (Niepoprawnie sformatowany kod lub cokolwiek innego).Jak napisać do okna wyjściowego Visual Studio w My Custom Tool?

Czy istnieją jakieś standardy w tym zakresie? Obecnie mogę zmusić narzędzie do awarii, a Visual Studio ostrzega, że ​​tak się stało. Chciałbym kategorii w oknie wyjściowym z wszelkich wynikowych wiadomości, które chcę wysłać. Mogę również żyć z bardziej opisowym zadaniem/ostrzeżeniem w oknie listy błędów.

+0

Dlaczego nie pisze się na standardowe wyjście działające dla Ciebie? – avakar

+0

pisanie wiadomości do Console.Write nie daje mi nic w oknie wyjściowym. –

Odpowiedz

44

Okno wyjściowe

Aby napisać do okna wyjściowego „Ogólne” w Visual Studio, należy wykonać następujące czynności:

IVsOutputWindow outWindow = Package.GetGlobalService(typeof(SVsOutputWindow)) as IVsOutputWindow; 

Guid generalPaneGuid = VSConstants.GUID_OutWindowGeneralPane; // P.S. There's also the GUID_OutWindowDebugPane available. 
IVsOutputWindowPane generalPane; 
outWindow.GetPane(ref generalPaneGuid , out generalPane); 

generalPane.OutputString("Hello World!"); 
generalPane.Activate(); // Brings this pane into view 

Jeśli jednak chcesz napisać do okna niestandardowego to co trzeba zrobić:

IVsOutputWindow outWindow = Package.GetGlobalService(typeof(SVsOutputWindow)) as IVsOutputWindow; 

// Use e.g. Tools -> Create GUID to make a stable, but unique GUID for your pane. 
// Also, in a real project, this should probably be a static constant, and not a local variable 
Guid customGuid = new Guid("0F44E2D1-F5FA-4d2d-AB30-22BE8ECD9789"); 
string customTitle = "Custom Window Title"; 
outWindow.CreatePane(ref customGuid, customTitle, 1, 1); 

IVsOutputWindowPane customPane; 
outWindow.GetPane(ref customGuid, out customPane); 

customPane.OutputString("Hello, Custom World!"); 
customPane.Activate(); // Brings this pane into view 

Szczegóły dotyczące IVsOutputWindow i IVsOutputWindowPane można znaleźć w witrynie MSDN.

Lista błędów

Do dodawania elementów do listy błędzie IVsSingleFileGenerator ma wywołanie metody void Generate(...) który ma parametr typu IVsGeneratorProgress. Ten interfejs ma metodę void GeneratorError(), która umożliwia zgłaszanie błędów i ostrzeżeń do listy błędów programu Visual Studio.

public class MyCodeGenerator : IVsSingleFileGenerator 
{ 
    ... 
    public void Generate(string inputFilePath, string inputFileContents, string defaultNamespace, out IntPtr outputFileContents, out int output, IVsGeneratorProgress generateProgress) 
    { 
     ... 
     generateProgress.GeneratorError(false, 0, "An error occured", 2, 4); 
     ... 
    } 
    ... 
} 

Szczegóły dotyczące GeneratorError() można znaleźć na stronie MSDN.

+0

Dla niestandardowego okna: jeśli I (VS2010) używa twojego rozwiązania, otrzymuję ładne okienko, które nic nie wyświetla. Jeśli zmienię to na outWindow.CreatePane (ref customGuid, customTitle, 1, 0); wszystko jest dobrze ... Ta zmiana oznacza, że ​​okno nie zostanie wyczyszczone po zamknięciu rozwiązania i nie widzę powodu, dla którego jest to konieczne, aby okno mogło wyświetlić cokolwiek. Czy możesz? – BennyBarns

+0

Przepraszam, nie mam pojęcia. Napisałem to na VS2008 i od tego czasu nie zajmowałem się rozwojem wtyczek VS ... – Alex

+0

W moim przypadku panel nie aktywuje się. 'customPane.Activate();' nie działa. dowolny pomysł? –

4

Jeśli chcesz, aby cokolwiek pojawiło się w oknie Output, musi pochodzić ze standardowego wyjścia. Aby to zrobić, Twoja aplikacja musi być połączona jako aplikacja "konsolowa". Ustaw flagę/SUBSYSTEM: CONSOLE na stronie właściwości projektu, pod Linker/System ustaw właściwość podsystemu na CONSOLE.

Po wyświetleniu danych w oknie, jeśli podasz tekst "Błąd:", pojawi się on jako błąd lub jeśli ustawisz "Ostrzeżenie:" pojawi się jako ostrzeżenie. Jeśli tekst błędu zaczyna się od ścieżki/nazwy pliku, a następnie numeru wiersza w nawiasie, IDE rozpozna go jako "klikalny" błąd i automatycznie przejdzie do linii błędu.

+0

Robię to w języku C# i nie ma rzeczy/podsystemu we właściwości projektu, czy muszę zrobić aplikację konsoli, aby to zrobić? działa teraz jako DLL, ale oczywiście nie otrzymuję danych wyjściowych. –

+0

To jest DLL? Jak się go wywołuje? Zwykle okno wyjściowe przechwytuje narzędzia, które są wykonywane w łańcuchu narzędzi, który konstruuje MSBuild, ale o ile wiedziałem, wszystkie te były niezależnymi plikami wykonywalnymi, a MSBuild po prostu przechwycił wszystkie standardowe wyjścia do wyświetlania w oknie. Po prostu przyszło mi do głowy, że twoje niestandardowe narzędzie może nie być związane z budowaniem. Okno "Wyjście" jest zarezerwowane dla procesu budowania. Jeśli chcesz uzyskać informacje o czasie wykonywania, powinieneś używać okna debugowania (z OutputDebugString() lub Debug.Print() lub czymkolwiek.) –

+2

Dzięki, John. Odkryłem, jak utworzyć błąd w MSBuild przez szczęście i szukałem w Internecie informacji o tym, jak utworzyć ostrzeżenie. Co ciekawe, Twój opis nie działa bezpośrednio dla mnie. Mam to do pracy, wypisując ": warning: " (bez cytatów). Visual Studio poszukiwało wiodącej okrężnicy, która służy do oddzielania pliku/linii # informacji od tekstu ostrzegawczego, jeśli ostrzeżenie jest powiązane z konkretnym plikiem/linią #. Z jakiegoś powodu VS 2008 nie zaakceptuje tylko "ostrzeżenia: tekst". Nie miało też znaczenia, czy strumień wyjściowy był stdout, stderr itp. I rozróżniana jest wielkość liter. Geesh. –

-2

użycie System.Diagnostics.Debugger.Message

7

Jest też inny sposób korzystania Marshal.GetActiveObject aby pobrać aktualny DTE2 instancji.

Pierwsze odniesienie EnvDTE i envdte80. To obecnie działa w Visual Studio 2012, nie próbowałem jeszcze innych.

using System; 
using System.Runtime.InteropServices; 
using EnvDTE; 
using EnvDTE80; 

internal class VsOutputLogger 
{ 
    private static Lazy<Action<string>> _Logger = new Lazy<Action<string>>(() => GetWindow().OutputString); 

    private static Action<string> Logger 
    { 
     get { return _Logger.Value; } 
    } 

    public static void SetLogger(Action<string> logger) 
    { 
     _Logger = new Lazy<Action<string>>(() => logger); 
    } 

    public static void Write(string format, params object[] args) 
    { 
     var message = string.Format(format, args); 
     Write(message); 
    } 

    public static void Write(string message) 
    { 
     Logger(message + Environment.NewLine); 
    } 

    private static OutputWindowPane GetWindow() 
    { 
     var dte = (DTE2) Marshal.GetActiveObject("VisualStudio.DTE"); 
     return dte.ToolWindows.OutputWindow.ActivePane; 
    } 
} 
+0

Zaakceptowana odpowiedź nie działa dla mnie w VS2010, podczas gdy ta ma wartość – smirkingman

+2

Mimo że działa to, jeśli wiele instancji Visual Studio jest otwartych, wiadomość prawdopodobnie kończy się w pierwszej otwartej. –