Question

I am writing a custom tool and I currently have it doing what I want as far as functionality. I would like to be able to write to Visual Studio if something goes wrong. (Incorrectly formatted code or whatever).

Are there any standards for this? Right now I basically can force the tool to fail and Visual Studio puts in a warning that it has done so. I'd like a category in the Output window with any resulting messages I want to send. I could also live with a more descriptive task/warning in the Error list window.

Was it helpful?

Solution

Output Window

To write to the "General" output window in Visual Studio, you need to do the following:

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

If, however, you want to write to a custom window, this is what you need to do:

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 on IVsOutputWindow and IVsOutputWindowPane can be found on MSDN.

Error List

For adding items to the error list, the IVsSingleFileGenerator has a method call void Generate(...) which has a parameter of the type IVsGeneratorProgress. This interface has a method void GeneratorError() which lets you report errors and warnings to the Visual Studio error list.

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

The details of GeneratorError() can be found on MSDN.

OTHER TIPS

There is another way using Marshal.GetActiveObject to grab a running DTE2 instance.

First reference EnvDTE and envdte80. This currently works in VisualStudio 2012, I haven't tried the others yet.

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

If you want anything to appear in the Output window, it has to come from stdout. To do this, your app needs to be linked as a "console" app. Set the /SUBSYSTEM:CONSOLE flag in the project's property page, under Linker/System set the SubSystem property to CONSOLE.

Once you have your output in the window, if you include the text "Error:" it will appear as an error, or if you set "Warning:" it will appear as a warning. If your error text begins with a path/filename, followed by a line number in parenthesis, the IDE will recognize it as a "clickable" error, and navigate you automatically to the faulting line.

You can use the Debug and/or Trace classes. There is some information here: http://msdn.microsoft.com/en-us/library/bs4c1wda(VS.71).aspx

Best of luck.

use System.Diagnostics.Debugger.Message

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top