21

I need to call a 3rd party library that happens to spew a bunch of stuff to the console. The code simply like this...

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

Is there an easy way to suppress the unwanted console output from ThirdPartyLibrary? For performance reasons, new processes or threads cannot be used in the solution.

Cœur
  • 37,241
  • 25
  • 195
  • 267
noctonura
  • 12,763
  • 10
  • 52
  • 85

2 Answers2

21

Well you can use Console.SetOut to an implementation of TextWriter which doesn't write anywhere:

Console.SetOut(TextWriter.Null);

That will suppress all console output though. You could always maintain a reference to the original Console.Out writer and use that for your own output.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    This does work in most cases. However, in my case it does not. The external library creates a COM object and at least 1 other thread - possibly even another process so that is complicating my problem. – noctonura Sep 11 '09 at 18:16
  • 2
    Ah. It would have been nice to have known that originally... if it's creating other processes or writing the the console in ways other than using `Console.WriteLine` etc, that does make things a lot harder... – Jon Skeet Sep 11 '09 at 18:22
  • 1
    Yes - sorry, I didn't realize that was important until trying your suggestion. – noctonura Sep 11 '09 at 18:31
  • I am having an issue where a dependent Managed C++ assembly is executing C++ library code with `sprintf` and `fprintf` commands. Issuing `Console.SetOut(TextWriter.Null)` doesn't have any affect. @jon-skeet any ideas? – Aaron Hudon Jan 25 '17 at 00:12
  • 1
    @AaronHudon: Well `sprintf` formats into memory and `fprintf` writes to a file... neither of them automatically writes to stdout. I suggest you ask a new question with more details. – Jon Skeet Jan 25 '17 at 06:48
  • my bad about the `sprintf`, it is the `fprintf( stdout ... )` that is still being written. I'll write up a new question – Aaron Hudon Jan 25 '17 at 16:43
7

Here's one way to do it (which also usually covers managed C++ applications that you P/Invoke from C# or otherwise):

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

This class can be called as follows:

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

This will have an impact. Any application logic that tries to use the console from another thread during the time you are using the OutputSink will not function correctly to write to the standard output, standard error, console output, or console error.

Alexandru
  • 12,264
  • 17
  • 113
  • 208
  • Looked good, bonus points for disposable logic, but didn't work in my case. I do PInvoke into some native code, but it seems they have different ways to write to my precious console. – Patrick Stalph Nov 21 '18 at 13:50