2009-07-07 9 views
27

Ich schreibe ein benutzerdefiniertes Werkzeug und ich habe es derzeit tun, was ich will, soweit es Funktionalität. Ich möchte in Visual Studio schreiben können, wenn etwas schief geht. (Falsch formatierter Code oder was auch immer).Wie schreibe ich in das Visual Studio-Ausgabefenster in Mein benutzerdefiniertes Tool?

Gibt es irgendwelche Standards dafür? Im Moment kann ich das Tool zum Fehlschlagen zwingen und Visual Studio gibt eine Warnung aus, dass es das getan hat. Ich möchte eine Kategorie im Ausgabefenster mit allen resultierenden Nachrichten, die ich senden möchte. Ich könnte auch mit einer beschreibenden Aufgabe/Warnung im Fenster Fehlerliste leben.

+0

Warum schreibt das Schreiben auf Standardausgabe nicht für Sie? – avakar

+0

Schreiben einer Nachricht an Console.Write gibt mir nichts im Ausgabefenster. –

Antwort

44

Ausgabefenster

auf „Allgemein“ Ausgabefenster in Visual Studio zu schreiben, müssen Sie folgendes tun:

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 

Wenn Sie jedoch zu einem benutzerdefinierten Fenster schreiben möchten, das ist, was Sie tun müssen:

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 

Details zu IVsOutputWindow und IVsOutputWindowPane auf MSDN.

Fehlerliste

Für Elemente der Fehlerliste hinzugefügt hat die IVsSingleFileGenerator einen Methodenaufruf void Generate(...) die IVsGeneratorProgress einen Parameter des Typs hat. Diese Schnittstelle verfügt über eine Methode void GeneratorError(), mit der Sie Fehler und Warnungen an die Visual Studio-Fehlerliste melden können.

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); 
     ... 
    } 
    ... 
} 

Die Details GeneratorError() auf MSDN.

+0

Für das benutzerdefinierte Fenster: Wenn ich (VS2010) Ihre Lösung verwende, bekomme ich ein nettes Fenster, das nichts anzeigt. Wenn ich es in outWindow.CreatePane ändern (ref customGuid, customTitle, 1, 0); alles ist gut ... Diese Änderung bedeutet, dass das Fenster nicht gelöscht wird, nachdem die Lösung geschlossen wurde, und ich kann nicht sehen, warum dies notwendig ist, damit das Fenster überhaupt etwas anzeigt. Können Sie? – BennyBarns

+0

Sorry, ich habe keine Ahnung. Ich habe dieses Ding für VS2008 geschrieben und ich habe mich seither nicht wirklich mit der Entwicklung von VS-Plugins beschäftigt ... – Alex

+0

In meinem Fall wird das Panel nicht aktiviert. 'customPane.Activate();' funktioniert nicht. irgendeine Idee? –

4

Wenn Sie möchten, dass etwas im Ausgabefenster erscheint, muss es von stdout kommen. Dazu muss Ihre App als "Konsolen" -App verknüpft sein. Setzen Sie das Flag/SUBSYSTEM: CONSOLE auf der Eigenschaftsseite des Projekts unter Linker/System setzen Sie die SubSystem-Eigenschaft auf CONSOLE.

Sobald Sie Ihre Ausgabe im Fenster haben, wenn Sie den Text "Error:" enthalten, wird es als ein Fehler angezeigt, oder wenn Sie "Warnung:" einstellen, wird es als eine Warnung angezeigt. Wenn Ihr Fehlertext mit einem Pfad/Dateinamen beginnt, gefolgt von einer Zeilennummer in Klammern, erkennt die IDE diesen Fehler als "anklickbar" und navigiert Sie automatisch zur fehlerhaften Zeile.

+0

Ich mache das in C# und es gibt keine/subsystem Zeug in der Projekt-Eigenschaft, muss ich eine Konsole App machen, dies zu tun? Es funktioniert jetzt als DLL, aber offensichtlich bekomme ich die Ausgabe nicht. –

+0

Es ist eine DLL? Wie wird es aufgerufen? Normalerweise erfasst das Ausgabefenster die Werkzeuge, die in der Werkzeugkette ausgeführt werden, die MSBuild konstruiert, aber soweit ich wusste, waren dies alles unabhängige ausführbare Dateien, und MSBuild würde einfach alle stdout für die Anzeige im Fenster erfassen. Es ist mir gerade in den Sinn gekommen, dass Ihr benutzerdefiniertes Tool möglicherweise nicht mit dem Bauen verbunden ist. Das Fenster "Ausgabe" ist für den Build-Prozess reserviert. Wenn Sie nach Laufzeitinformationen suchen, sollten Sie das Debug-Fenster verwenden (mit OutputDebugString() oder Debug.Print() oder was auch immer.) –

+2

Danke, John. Ich habe durch Zufall entdeckt, wie man einen Fehler in MSBuild erstellt und im Internet nach einer Warnung gesucht. Interessanterweise funktionierte Ihre Beschreibung nicht direkt für mich. Ich habe es funktioniert, indem ich ": warning: " (ohne Anführungszeichen) ausgegeben habe. Visual Studio wollte den führenden Doppelpunkt, der verwendet wird, um die Datei/Zeile # Info vom Warntext zu trennen, wenn die Warnung einer bestimmten Datei/Zeile # zugeordnet ist. Aus irgendeinem Grund akzeptiert VS 2008 nicht nur "Warnung: Text". Es war auch egal, ob der Ausgabestrom stdout, stderr usw. war. Und es ist die Groß- und Kleinschreibung. Geesh. –

-2

Verwendung System.Diagnostics.Debugger.Message

7

Es gibt eine andere Art und Weise Marshal.GetActiveObject unter Verwendung der aktuellen DTE2 Instanz zu greifen.

Erste Referenz EnvDTE und envdte80. Dies funktioniert derzeit in VisualStudio 2012, ich habe die anderen noch nicht ausprobiert.

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

Die angenommene Antwort funktioniert nicht in VS2010 für mich, während dies funktioniert – smirkingman

+2

Obwohl dies funktioniert, wenn Sie mehrere Visual Studio-Instanzen geöffnet haben, wird die Nachricht wahrscheinlich in der ersten Sie geöffnet. –