抑制第三方库的控制台输出?

21

我需要调用一个第三方库,这个库会向控制台输出大量内容。代码看起来像这样...

int MyMethod(int a)
{
   int b = ThirdPartyLibrary.Transform(a);  // spews unwanted console output
   return b;
}

有没有一种简单的方法可以抑制ThirdPartyLibrary产生的不必要的控制台输出?出于性能原因,解决方案中不能使用新的进程或线程。

2个回答

21

你可以使用 Console.SetOut 方法将其输出流设置为一个未写入任何内容的 TextWriter 实现:

Console.SetOut(TextWriter.Null);

这将抑制所有控制台输出。 你可以始终保留对原始Console.Out编写器的引用,并使用它来进行自己的输出。


1
这在大多数情况下工作良好。然而,在我的情况下却不是这样。外部库创建了一个COM对象和至少1个其他线程 - 可能甚至是另一个进程,从而使我的问题变得复杂。 - noctonura
2
啊,最好最开始就知道这个……如果它创建其他进程或以其他方式编写控制台而不是使用“Console.WriteLine”等等,这会让事情变得更加困难…… - Jon Skeet
1
是的 - 对不起,直到尝试了您的建议,我才意识到那很重要。 - noctonura
我遇到了一个问题,即一个依赖的Managed C++程序集正在执行带有sprintffprintf命令的C++库代码。发出Console.SetOut(TextWriter.Null)没有任何影响。@jon-skeet有什么想法吗? - Aaron Hudon
2
@AaronHudon:sprintf将格式化输出到内存中,而fprintf则将其写入文件中... 两者都不会自动写入stdout。我建议您提出一个带有更多细节的新问题。 - Jon Skeet
关于sprintf的问题,我搞错了,实际上是fprintf( stdout ... )还在被写入。我会写一个新的问题。 - Aaron Hudon

7
这里有一种方法可以实现(通常也适用于从C#调用或以其他方式P/Invoke的托管C ++应用程序):
internal class OutputSink : IDisposable
{
    [DllImport("kernel32.dll")]
    public static extern IntPtr GetStdHandle(int nStdHandle);

    [DllImport("kernel32.dll")]
    public static extern int SetStdHandle(int nStdHandle, IntPtr hHandle);

    private readonly TextWriter _oldOut;
    private readonly TextWriter _oldError;
    private readonly IntPtr _oldOutHandle;
    private readonly IntPtr _oldErrorHandle;

    public OutputSink()
    {
        _oldOutHandle = GetStdHandle(-11);
        _oldErrorHandle = GetStdHandle(-12);
        _oldOut = Console.Out;
        _oldError = Console.Error;
        Console.SetOut(TextWriter.Null);
        Console.SetError(TextWriter.Null);
        SetStdHandle(-11, IntPtr.Zero);
        SetStdHandle(-12, IntPtr.Zero);
    }

    public void Dispose()
    {
        SetStdHandle(-11, _oldOutHandle);
        SetStdHandle(-12, _oldErrorHandle);
        Console.SetOut(_oldOut);
        Console.SetError(_oldError);
    }
}

这个类可以按照以下方式调用:

using (new OutputSink())
{
    /* Call 3rd party library here... */
}

这将产生影响。在您使用 OutputSink 的过程中,任何试图从另一个线程使用控制台的应用程序逻辑都无法正确地写入标准输出、标准错误、控制台输出或控制台错误。


1
看起来不错,一次性逻辑加分,但在我的情况下不起作用。我进行了PInvoke到一些本地代码,但似乎它们有不同的方法来写入我的珍贵控制台。 - Patrick Stalph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接