none
How to Suppress Own Console Prompt in C#

    Question

  • Hi,

    I have a C# Console application which prompts the user for an input command line and which then performs various actions depending upon the commands entered. e.g. prompt = "Hello> ", etc. I am using the Console.Out TextReader to prompt the user and the Console.In TextReader to read the user commands.

    This works fine provided the session is interactive. The problem is how to suppress my own command prompt when stdin is redirected with e.g. a < or | at the cmd.exe command line. I.e. when the input is from a file rather than from the user directly. I.e. for batch / automated processing.

    A /batch or /b switch would be easy, but it should be possible to determine whether the TextReader is actually the user at the Console or a redirected file input. I have tried GetType(), but no success. I have also tried KeyAvailable and TextReader.Peek but that is of no use (Peek actually reads). I have also thought about timeout but the TextReader doesn't support that.

    I'm sure there is a really simple solution, but I just can't figure it out.

    Any help greatly appreciated.

    Charles
    Friday, October 02, 2009 1:58 PM

Answers

  • That is a strange omission from the Console class.  Fixable though.  Add a new class to your project and paste the code below.  Use ConsoleEx.OutputRedirected to check.

    using System;
    using System.Runtime.InteropServices;

    public static class ConsoleEx {
      public static bool OutputRedirected {
        get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stdout)); }
      }
      public static bool InputRedirected {
        get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stdin)); }
      }
      public static bool ErrorRedirected {
        get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stderr)); }
      }

      // P/Invoke:
      private enum FileType { Unknown, Disk, Char, Pipe };
      private enum StdHandle { Stdin = -10, Stdout = -11, Stderr = -12 };
      [DllImport("kernel32.dll")]
      private static extern FileType GetFileType(IntPtr hdl);
      [DllImport("kernel32.dll")]
      private static extern IntPtr GetStdHandle(StdHandle std);

    }

    Hans Passant.
    Friday, October 02, 2009 2:56 PM
  • Windows knows.  The error it returns when ReadKey tries to read a key generates the exception.

    Hans Passant.
    • Marked as answer by eryang Wednesday, October 14, 2009 2:40 AM
    Monday, October 05, 2009 9:13 AM

All replies

  • That is a strange omission from the Console class.  Fixable though.  Add a new class to your project and paste the code below.  Use ConsoleEx.OutputRedirected to check.

    using System;
    using System.Runtime.InteropServices;

    public static class ConsoleEx {
      public static bool OutputRedirected {
        get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stdout)); }
      }
      public static bool InputRedirected {
        get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stdin)); }
      }
      public static bool ErrorRedirected {
        get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stderr)); }
      }

      // P/Invoke:
      private enum FileType { Unknown, Disk, Char, Pipe };
      private enum StdHandle { Stdin = -10, Stdout = -11, Stderr = -12 };
      [DllImport("kernel32.dll")]
      private static extern FileType GetFileType(IntPtr hdl);
      [DllImport("kernel32.dll")]
      private static extern IntPtr GetStdHandle(StdHandle std);

    }

    Hans Passant.
    Friday, October 02, 2009 2:56 PM
  • Hi Hans,

    That's brilliant - thank you. Works a treat.

    I also noticed by the way that the Console ReadKey(true) method throws an exception if you use it with redirected input. So, the Console class does seem to know already, but one would need to know before using ReadKey(true) in order not to use it.

    Thanks again,
    Charles
    Monday, October 05, 2009 8:58 AM
  • Windows knows.  The error it returns when ReadKey tries to read a key generates the exception.

    Hans Passant.
    • Marked as answer by eryang Wednesday, October 14, 2009 2:40 AM
    Monday, October 05, 2009 9:13 AM