12

I have a console application written in C# which processes some data then prints the results. Until the results are available there is a little animation ( / - \ | ) and progress percentage ( xx% ) which is constantly updating.

Obviously if the user redirects the output of my application this will be printed to the text file where output is redirected to. If possible I would like to avoid this.

So is there a way to detect if the output of my application is redirected? I am considering only showing the progress indicators when run with a specified parameter, but I'm hoping someone will have a good answer for me.

Kate Gregory
  • 18,808
  • 8
  • 56
  • 85
Nippysaurus
  • 20,110
  • 21
  • 77
  • 129
  • Its interesting reading your question three years later and realizing how silly it was :-) if there is anyone reading this ... the correct way to approach this is most certainly to not show the progress bar by default ... only display it when a specific switch is used. – Nippysaurus Jul 26 '12 at 23:42
  • possible duplicate of [How can I determine whether Console.Out has been redirected to a file?](http://stackoverflow.com/questions/743885/how-can-i-determine-whether-console-out-has-been-redirected-to-a-file) – Kate Gregory Dec 28 '12 at 16:06

7 Answers7

15

From .NET Framework 4.5 onwards you can use the Console.IsOutputRedirected property to detect this.

There's also Console.IsErrorRedirected.

phonetagger
  • 7,701
  • 3
  • 31
  • 55
Matt Brooks
  • 1,584
  • 1
  • 14
  • 27
7

As it turns out, it soon will be available in the elegant and cross-platform way: link.

konrad.kruczynski
  • 46,413
  • 6
  • 36
  • 47
6

You can use the native method GetConsoleMode to see if stdout is going to a console or not.

This method is suggested by the remarks in the documentation for WriteConsole:

... determine whether the output handle is a console handle (one method is to call the GetConsoleMode function and check whether it succeeds)...

Stobor
  • 44,246
  • 6
  • 66
  • 69
  • Grannted, that means using unsafe native methods... But it's possible. – Stobor Jul 23 '09 at 05:12
  • 1
    Some properties call `GetConsoleMode` and throw on failure, such as `Console.CursorVisible`. That would allow checking for console output without using P/Invoke. – Medinoc May 05 '17 at 12:56
3

You can't. Redirected output is totally and wholly outside the scope of the executing program. You can however add a commandline option to disable your pretty output so that it can be used redirected too.

EDIT: You CAN (now)... with .NET 4.5 onwards (see Matt Brooks' answer).

Community
  • 1
  • 1
Matthew Scharley
  • 127,823
  • 52
  • 194
  • 222
  • Just as I thought >.< Might just have to go with the cli parameter option. – Nippysaurus Jul 23 '09 at 04:41
  • What if I want to guess some default settings depending on whether the input goes from console or not? For example, in SQL parser it's good to print the resulting recordset when accepting commands from the keyboard, but be silent when parsing file. Or what if I care to output the Unicode BOM when writing to file? What are the patterns that should be used in these cases? – himself Aug 23 '10 at 10:27
  • @himself: If you want to handle stuff like writing a BOM, then ask for an output parameter. Depending on the OS, you can detect if you're running on a console, but it's convoluted to say the least, and it doesn't work on Windows/C# I don't think. Your simplest bet is to accept a `-q` (quiet) or similar option, or perhaps assume you're getting programmed input if you've got said option enabled to write to a file. – Matthew Scharley Aug 23 '10 at 11:58
3

Rather than trying to determine whether or not the content is redirected, I would use Console.WriteLine (or Console.Out.WriteLine) to print your results and Console.Error.Write for your status updates. The screen output will show properly but not be reflected in the text file.

DocMax
  • 12,094
  • 7
  • 44
  • 44
2

Probably, you can try this:

public enum FileType : uint
{
    FILE_TYPE_UNKNOWN = 0x0000,
    FILE_TYPE_DISK = 0x0001,
    FILE_TYPE_CHAR = 0x0002,
    FILE_TYPE_PIPE = 0x0003,
    FILE_TYPE_REMOTE = 0x8000,
}

public enum STDHandle : uint
{
    STD_INPUT_HANDLE = unchecked((uint)-10),
    STD_OUTPUT_HANDLE = unchecked((uint)-11),
    STD_ERROR_HANDLE = unchecked((uint)-12),
}

[DllImport("Kernel32.dll")]
static public extern UIntPtr GetStdHandle(STDHandle stdHandle);
[DllImport("Kernel32.dll")]
static public extern FileType GetFileType(UIntPtr hFile);

static public bool IsOutputRedirected()
{
    UIntPtr hOutput = GetStdHandle(STDHandle.STD_OUTPUT_HANDLE);
    FileType fileType = (FileType)GetFileType(hOutput);
    if (fileType == FileType.FILE_TYPE_CHAR)
        return false;
    return true;
}

If the standard output is not redirected, the output of the GetFileType() should be 0x0002. This works for me. :)

Elliott
  • 141
  • 3
  • 14
0

Console.Write("whatever") (and WriteLine) actually write data to the stream behind Console.Out. To always show a progress bar on the console and not write it to a file, no matter if the output is redirected to a file or not, use the error stream instead:

Console.Error.Write("<your progress bar>");

When an application redirects output with the > operator (DIR C:\*.*>MORE), only Console.Out is redirected and not Console.Error

AyrA
  • 763
  • 10
  • 17