17

If my program is printing to the console, I perform word-wrapping in a certain way according to Console.WindowWidth by inserting newlines - and this works perfectly.

However if the output of the program is redirected to a file or another program I would like it to skip the word-wrapping. How can I detect when this is the case?

Console.WindowWidth returns the same number in both cases.

Bonus points if the solution can distinguish redirected Console.Out from redirected Console.Error.

Roman Starkov
  • 59,298
  • 38
  • 251
  • 324
  • possible duplicate of [Check if output is redirected](http://stackoverflow.com/questions/1169591/check-if-output-is-redirected) – Kate Gregory Dec 28 '12 at 16:09

6 Answers6

15

.NET 4.5 adds Console.IsOutputRedirected and Console.IsErrorRedirected.

Roger Lipscombe
  • 89,048
  • 55
  • 235
  • 380
11

p/invoke GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)), or call an innocuous console function like GetConsoleScreenBufferInfo to check for invalid handle error. If you want to know about standard error, use STD_ERROR_HANDLE. I believe you can even compare handles returned by GetStdHandle(STD_OUTPUT_HANDLE) and GetStdHandle(STD_ERROR_HANDLE) to detect stuff like 2>&1.

Anton Tykhyy
  • 19,370
  • 5
  • 54
  • 56
8

While this is a little shady and probably isn't guaranteed to work, you can try this:

bool isRedirected;

try
{
    isRedirected = Console.CursorVisible && false;
}
catch
{
    isRedirected = true;
}

Calling CursorVisible throws an exception when the console is redirected.

Adam Robinson
  • 182,639
  • 35
  • 285
  • 343
  • Seems to work for stdout. Provides no distinction between cases when only stderr, only stdout or both are redirected. Still ok for some use cases though. – Roman Starkov Apr 13 '09 at 13:59
  • It always worked for me when stdout was redirected, which I would imagine is really the only one that would matter, right? – Adam Robinson Apr 13 '09 at 14:18
2

You need to use reflection - a bit grubby but the following will work:

static bool IsConsoleRedirected()
{
    var writer = Console.Out;
    if (writer == null || writer.GetType ().FullName != "System.IO.TextWriter+SyncTextWriter") return true;
    var fld = writer.GetType ().GetField ("_out", BindingFlags.Instance | BindingFlags.NonPublic);
    if (fld == null) return true;
    var streamWriter = fld.GetValue (writer) as StreamWriter;
    if (streamWriter == null) return true;
    return streamWriter.BaseStream.GetType ().FullName != "System.IO.__ConsoleStream";
}
Joe Albahari
  • 30,118
  • 7
  • 80
  • 91
  • And how do you make sure it will work in the next version of .NET as well? :) – ibz Apr 13 '09 at 13:57
  • That's why it's a bit grubbly. But it's the only option. – Joe Albahari Apr 13 '09 at 14:00
  • While it does nasty stuff like checking the name of the type of a private field... It's still the best solution so far and others are not much less nasty. – Roman Starkov Apr 13 '09 at 14:01
  • I think it's an OK technique. You'd definitely want to have it covered by unit tests, to make sure it worked across framework version changes. – RichardOD Mar 05 '10 at 12:39
0

Why does the ouput wrap in the redirected file? The wrapping that the console does is not by means of line breaks. In other words this string:

hello my name is Andrew Hare

would wrap in a skinny console like this:

hello my nam
e is Andrew
Hare

but if you were to redirect the output to a file it would be written like this:

hello my name is Andrew Hare

since there are no true line-breaks in the output.

Andrew Hare
  • 344,730
  • 71
  • 640
  • 635
  • Exactly - in a skinny console it would be wrapped in a crappy way. Which is why we're wrapping ourselves (by inserting newlines and appropriate indentation) before outputting to the console. Obviously this approach also wraps the redirected output, which is what we're trying to avoid. – Roman Starkov Apr 13 '09 at 13:38
0

Don't do that! Just pass an additional command line parameter that specifies the formatting you want to be applied. It's simpler, cleaner, and easier to understand both by people that will use your app and by people who will work on your code.

ibz
  • 44,461
  • 24
  • 70
  • 86
  • 4
    I disagree. Programs should figure things out by themselves to as large an extent as possible, and not ask the user every time. – Anton Tykhyy Apr 13 '09 at 15:08
  • 1
    Disagree as well. Look at how git behaves. Commands like `git diff` pipe through less and some kind of colorizer unless they are piped or redirected to a file. – Justin Dearing Mar 13 '12 at 11:41