Matt
Matt

Reputation: 61

C# -- Console.In.ReadToEnd() hangs on user input if no data piped to program

I'm writing a C# console application that takes 2 parameters: myprogram.exe param1 param2

param2 is optional, and the idea is if it's not present, get piped data:

echo "hithere" | myprogram.exe param1

I've made this part work by capturing Console.In.ReadToEnd() when only 1 parameter is passed.

The problem I'm facing is when only 1 parameter is passed and no data is piped, it just sits there listening to user input and the only way to close out is to Ctrl+C to end the program.

Instead, is there a way to return an error and quit the program if only 1 parameter was supplied and no data was piped ?


To test if there is anything waiting, I've tried using:

That didn't work.

I've also tried the 'hack' mentioned at the bottom of this stackoverflow question: C# Console receive input with pipe .

Any ideas?

Upvotes: 6

Views: 4321

Answers (2)

Walter
Walter

Reputation: 528

You could the following program to check to see if standard in is redirected:

using System;
using System.Runtime.InteropServices;

public static class ConsoleEx {
  public static bool IsOutputRedirected {
    get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stdout)); }
  }
  public static bool IsInputRedirected {
    get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stdin)); }
  }
  public static bool IsErrorRedirected {
    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);
}

Usage:

bool inputRedirected = ConsoleEx.IsInputRedirected;

Then check for the number of command line parameters:

if (args.Length < 1)
# No parameters were passed
if (args.Length < 2)
{
   if (!inputRedirected)
   {
      Console.Error.WriteLine("You must redirect from stdin");
      # exit/die/end here
   }
}

I copied this from https://stackoverflow.com/a/3453272/17034

Upvotes: -1

OJ.
OJ.

Reputation: 29399

Instead of checking the console, check the command line. If they pass in enough arguments, then assume there is nothing to get from the console. If they don't specify enough parameters then assume the URL is going to come from the console. You don't need to use ReadToEnd(), just use ReadLine() instead so you can go line by line. If you use ReadToEnd() you'll have to hit CTRL+Z (or CTRL+D in linux) to indicate the end of the input stream.

Upvotes: 5

Related Questions