【问题标题】:How do I write to the Visual Studio Output Window in My Custom Tool?如何在我的自定义工具中写入 Visual Studio 输出窗口?
【发布时间】:2009-07-07 19:36:56
【问题描述】:

我正在编写一个自定义工具,我目前正在使用它来做我想要的功能。如果出现问题,我希望能够写信给 Visual Studio。 (格式不正确的代码或其他)。

这有什么标准吗?现在我基本上可以强制该工具失败,Visual Studio 会发出警告说它已经这样做了。我想要输出窗口中的一个类别,其中包含我想要发送的任何结果消息。我还可以在错误列表窗口中接受更具描述性的任务/警告。

【问题讨论】:

  • 为什么写入标准输出对您不起作用?
  • 向 Console.Write 写入消息不会在输出窗口中给我任何信息。

标签: visual-studio vsx customtool


【解决方案1】:

输出窗口

要写入 Visual Studio 中的“常规”输出窗口,您需要执行以下操作:

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

但是,如果您想写入自定义窗口,则需要执行以下操作:

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

IVsOutputWindowIVsOutputWindowPane 的详细信息可以在 MSDN 上找到。

错误列表

为了将项目添加到错误列表中,IVsSingleFileGenerator 有一个方法调用 void Generate(...),它有一个类型为 IVsGeneratorProgress 的参数。这个接口有一个方法void GeneratorError(),可以让你向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);
        ...
    }
    ...
}

GeneratorError()的详细信息可以在MSDN上找到。

【讨论】:

  • 对于自定义窗口:如果我(VS2010)使用您的解决方案,我会得到一个漂亮的窗格,它什么都不显示。如果我将其更改为 outWindow.CreatePane( ref customGuid, customTitle, 1, 0 );一切都很好......这个变化意味着在解决方案关闭后窗口没有被清除,我不明白为什么窗口需要显示任何东西。可以吗?
  • 对不起,我不知道。这个东西是我为VS2008写的,从那时起我就没有真正接触过VS插件开发了……
  • 在我的情况下,面板没有激活。 customPane.Activate(); 不工作。有什么想法吗?
【解决方案2】:

还有另一种方法使用Marshal.GetActiveObject 来获取正在运行的DTE2 实例。

首先参考 EnvDTE 和 envdte80。这目前在 VisualStudio 2012 中有效,我还没有尝试过其他的。

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

【讨论】:

  • 接受的答案对我来说在 VS2010 中不起作用,而这却是
  • 虽然这可行,但如果您打开了多个 Visual Studio 实例,则该消息可能会在您打开的第一个实例中结束。
【解决方案3】:

如果您希望任何内容出现在“输出”窗口中,它必须来自标准输出。为此,您的应用需要链接为“控制台”应用。在项目的属性页中设置 /SUBSYSTEM:CONSOLE 标志,在 Linker/System 下将 SubSystem 属性设置为 CONSOLE。

在窗口中输出后,如果包含文本“错误:”,它将显示为错误,或者如果您设置“警告:”,它将显示为警告。如果您的错误文本以路径/文件名开头,后跟括号中的行号,IDE 会将其识别为“可点击”错误,并自动将您导航到错误行。

【讨论】:

  • 我在 C# 中执行此操作,并且项目属性中没有 /subsystem 内容,我需要制作控制台应用程序来执行此操作吗?它现在作为 DLL 工作,但显然我没有得到输出。
  • 它是一个DLL?它是如何被调用的?通常,输出窗口会捕获在 MSBuild 构建的工具链中执行的工具,但据我所知,这些都是独立的可执行文件,MSBuild 只会捕获所有标准输出以在窗口中显示。我突然想到您的自定义工具可能与构建无关。 “输出”窗口是为构建过程保留的。如果您希望输出运行时信息,您应该使用调试窗口(使用 OutputDebugString() 或 Debug.Print() 或其他)。
  • 谢谢,约翰。我发现了如何通过运气在 MSBuild 中创建错误,并在网上搜索如何创建警告。有趣的是,您的描述对我没有直接作用。我通过输出 ":warning: " (不带引号)让它工作。如果警告与特定文件/行# 相关联,Visual Studio 需要前导冒号,用于将文件/行# 信息与警告文本分开。出于某种原因,VS 2008 不会只接受“警告:文本”。此外,输出流是否为 stdout、stderr 等也没关系。它区分大小写。天哪。
【解决方案4】:

您可以使用 Debug 和/或 Trace 类。这里有一些信息: http://msdn.microsoft.com/en-us/library/bs4c1wda(VS.71).aspx

祝你好运。

【讨论】:

  • 我在问这个之前尝试了 trace.write (message, category) 并且它没有输出。
【解决方案5】:

Microsoft 示例项目的以下帮助程序类对此进行了演示:

https://github.com/microsoft/VSSDK-Extensibility-Samples/blob/df10d37b863feeff6e8fcaa6f4d172f602a882c5/Reference_Services/C%23/Reference.Services/HelperFunctions.cs#L28

代码如下:

using System;
using System.Diagnostics;
using Microsoft.VisualStudio.Shell.Interop;

namespace Microsoft.Samples.VisualStudio.Services
{
    /// <summary>
    /// This class is used to expose some utility functions used in this project.
    /// </summary>
    internal static class HelperFunctions
    {
        /// <summary>
        /// This function is used to write a string on the Output window of Visual Studio.
        /// </summary>
        /// <param name="provider">The service provider to query for SVsOutputWindow</param>
        /// <param name="text">The text to write</param>
        internal static void WriteOnOutputWindow(IServiceProvider provider, string text)
        {
            // At first write the text on the debug output.
            Debug.WriteLine(text);

            // Check if we have a provider
            if (null == provider)
            {
                // If there is no provider we can not do anything; exit now.
                Debug.WriteLine("No service provider passed to WriteOnOutputWindow.");
                return;
            }

            // Now get the SVsOutputWindow service from the service provider.
            IVsOutputWindow outputWindow = provider.GetService(typeof(SVsOutputWindow)) as IVsOutputWindow;
            if (null == outputWindow)
            {
                // If the provider doesn't expose the service there is nothing we can do.
                // Write a message on the debug output and exit.
                Debug.WriteLine("Can not get the SVsOutputWindow service.");
                return;
            }

            // We can not write on the Output window itself, but only on one of its panes.
            // Here we try to use the "General" pane.
            Guid guidGeneral = Microsoft.VisualStudio.VSConstants.GUID_OutWindowGeneralPane;
            IVsOutputWindowPane windowPane;
            if (Microsoft.VisualStudio.ErrorHandler.Failed(outputWindow.GetPane(ref guidGeneral, out windowPane)) ||
                (null == windowPane))
            {
                if (Microsoft.VisualStudio.ErrorHandler.Failed(outputWindow.CreatePane(ref guidGeneral, "General", 1, 0)))
                {
                    // Nothing to do here, just debug output and exit
                    Debug.WriteLine("Failed to create the Output window pane.");
                    return;
                }
                if (Microsoft.VisualStudio.ErrorHandler.Failed(outputWindow.GetPane(ref guidGeneral, out windowPane)) ||
                (null == windowPane))
                {
                    // Again, there is nothing we can do to recover from this error, so write on the
                    // debug output and exit.
                    Debug.WriteLine("Failed to get the Output window pane.");
                    return;
                }
                if (Microsoft.VisualStudio.ErrorHandler.Failed(windowPane.Activate()))
                {
                    Debug.WriteLine("Failed to activate the Output window pane.");
                    return;
                }
            }

            // Finally we can write on the window pane.
            if (Microsoft.VisualStudio.ErrorHandler.Failed(windowPane.OutputString(text)))
            {
                Debug.WriteLine("Failed to write on the Output window pane.");
            }
        }
    }
}

【讨论】:

    【解决方案6】:

    使用System.Diagnostics.Debugger.Message

    【讨论】:

      猜你喜欢
      • 2010-11-12
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      • 2018-06-15
      • 1970-01-01
      • 2018-06-19
      • 1970-01-01
      相关资源
      最近更新 更多