2009-07-07 22 views
27

Estoy escribiendo una herramienta personalizada y actualmente lo tengo haciendo lo que quiero en cuanto a funcionalidad. Me gustaría poder escribir en Visual Studio si algo sale mal. (Código formateado incorrectamente o lo que sea).¿Cómo escribo en la ventana de salida de Visual Studio en Mi herramienta personalizada?

¿Hay alguna norma para esto? En este momento, básicamente puedo forzar a la herramienta a fallar y Visual Studio advierte que lo ha hecho. Me gustaría una categoría en la ventana de resultados con los mensajes resultantes que deseo enviar. También podría vivir con una tarea/advertencia más descriptiva en la ventana de la lista de errores.

+0

¿Por qué la escritura en salida estándar no funciona para usted? – avakar

+0

escribiendo un mensaje a Console.Write no me da nada en la ventana de salida. –

Respuesta

44

ventana de salida

escribir en la ventana de salida "General" en Visual Studio, tiene que hacer lo siguiente:

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 

Sin embargo, si desea escribir en una ventana personalizada, esto es lo que hay que hacer:

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 

detalles sobre IVsOutputWindow y IVsOutputWindowPane se pueden encontrar en MSDN.

Lista de errores

Para añadir elementos a la lista de errores, el IVsSingleFileGenerator tiene una llamada al método void Generate(...) que tiene un parámetro del tipo IVsGeneratorProgress. Esta interfaz tiene un método void GeneratorError() que le permite informar errores y advertencias a la lista de errores de 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); 
     ... 
    } 
    ... 
} 

Los detalles de GeneratorError() se pueden encontrar en MSDN.

+0

Para la ventana personalizada: si yo (VS2010) uso su solución, obtengo un bonito panel de ventana que no muestra nada. Si lo cambio a outWindow.CreatePane (ref customGuid, customTitle, 1, 0); todo está bien ... Este cambio significa que la ventana no se borra después de que se cierra la solución, y no veo por qué esto es necesario para que la ventana muestre algo. ¿Puedes? – BennyBarns

+0

Lo siento, no tengo idea. Escribí esto para VS2008, y no he tratado realmente con el desarrollo del complemento VS desde ese momento ... – Alex

+0

En mi caso, el panel no se está activando. 'customPane.Activate();' no funciona. ¿alguna idea? –

4

Si desea que aparezca algo en la ventana de Salida, tiene que venir de stdout. Para hacer esto, su aplicación debe estar vinculada como una aplicación de "consola". Establezca el indicador/SUBSYSTEM: CONSOLE en la página de propiedades del proyecto, en Linker/System configure la propiedad SubSystem en CONSOLE.

Una vez que tenga su salida en la ventana, si incluye el texto "Error:" aparecerá como un error, o si establece "Advertencia:", aparecerá como una advertencia. Si su texto de error comienza con una ruta/nombre de archivo, seguido por un número de línea entre paréntesis, el IDE lo reconocerá como un error de "clic" y lo llevará automáticamente a la línea de fallas.

+0

Estoy haciendo esto en C# y no hay elementos de subsistema en la propiedad del proyecto, ¿necesito hacer una aplicación de consola para hacer esto? está funcionando ahora como una DLL, pero obviamente no obtengo el resultado. –

+0

Es una DLL? ¿Cómo se está invocando? Normalmente, la ventana de salida captura las herramientas que se ejecutan en la cadena de herramientas que MSBuild construye, pero hasta donde yo sabía, todas eran ejecutables independientes, y MSBuild simplemente capturaba todas las stdout para mostrarlas en la ventana. Se me acaba de ocurrir que su herramienta personalizada puede no estar relacionada con la construcción. La ventana "Salida" está reservada para el proceso de compilación. Si está buscando publicar información en tiempo de ejecución, debe usar la ventana de depuración (con OutputDebugString() o Debug.Print() o lo que sea). –

+2

Gracias, John. Descubrí cómo crear un error en MSBuild a través de la suerte y estaba buscando en la web cómo crear una advertencia. Curiosamente, su descripción no funcionó directamente para mí. Lo conseguí para trabajar sacando ": advertencia: " (sin las comillas). Visual Studio quería el colon inicial, que se usa para separar la información del archivo/línea # del texto de advertencia, si la advertencia está asociada con un archivo/número de línea en particular. Por alguna razón, VS 2008 no aceptará solo "advertencia: texto". Además, no importaba si el flujo de salida era stdout, stderr, etc. Y distingue entre mayúsculas y minúsculas. Geesh. –

-2

uso System.Diagnostics.Debugger.Message

7

hay otra manera usando Marshal.GetActiveObject para agarrar la corriente DTE2 ejemplo.

Primera referencia EnvDTE y envdte80. Esto actualmente funciona en VisualStudio 2012, todavía no he probado los demás.

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

La respuesta aceptada no funciona en VS2010 para mí, mientras que esto sí – smirkingman

+2

Aunque esto funciona, si tiene varias instancias de Visual Studio abiertas, el mensaje probablemente termine en el primero que abrió. –

Cuestiones relacionadas