48

I know how to program Console application with parameters, example : myProgram.exe param1 param2.

My question is, how can I make my program works with |, example : echo "word" | myProgram.exe?

Patrick Desjardins
  • 136,852
  • 88
  • 292
  • 341

8 Answers8

50

You need to use Console.Read() and Console.ReadLine() as if you were reading user input. Pipes replace user input transparently. You can't use both easily (although I'm sure it's quite possible...).

Edit:

A simple cat style program:

class Program
{
    static void Main(string[] args)
    {
        string s;
        while ((s = Console.ReadLine()) != null)
        {
            Console.WriteLine(s);
        }

    }
}

And when run, as expected, the output:

C:\...\ConsoleApplication1\bin\Debug>echo "Foo bar baz" | ConsoleApplication1.exe
"Foo bar baz"

C:\...\ConsoleApplication1\bin\Debug>
Matthew Scharley
  • 127,823
  • 52
  • 194
  • 222
  • 1
    Does your example works for : echo "Foo bar baz" | ConsoleApplication1.exe | ConsoleApplication1.exe ? – Patrick Desjardins Oct 14 '08 at 00:41
  • 3
    Yes. Using a lower level analogy, what really happens with a pipe is the Stdout stream of the first application gets plugged into the Stdin stream of the next application in the pipeline. The console's stdin get put through the first application, and the last applications stdout is displayed. – Matthew Scharley Oct 14 '08 at 00:44
  • 1
    If you're working with binary data: http://stackoverflow.com/questions/1562417/read-binary-data-from-console-in – sanmai Oct 03 '12 at 01:58
  • why check for ReadLine == null, does it ever return null? (Wouldn't it return empty string if nothing is entered). http://stackoverflow.com/questions/26338571/checking-console-readline-null – barlop Jun 11 '15 at 09:02
  • @barlop No it won't return an empty string. How would you retrieve lines that are empty then? The documentation of `Console.ReadLine` states that it returns null if there are no more lines to read: https://msdn.microsoft.com/de-de/library/system.console.readline(v=vs.110).aspx – Robert S. May 31 '16 at 08:47
  • @RobertS. yeah, thanks, quite right, btw, it returns null just when Ctrl-Z is pressed. (not Ctrl-C for example), so not any case of "no more lines to read". I see the msdn mentions the Ctrl+Z. – barlop May 31 '16 at 13:57
20

The following will not suspend the application for input and works when data is or is not piped. A bit of a hack; and due to the error catching, performance could lack when numerous piped calls are made but... easy.

public static void Main(String[] args)
{

    String pipedText = "";
    bool isKeyAvailable;

    try
    {
        isKeyAvailable = System.Console.KeyAvailable;
    }
    catch (InvalidOperationException expected)
    {
        pipedText = System.Console.In.ReadToEnd();
    }

    //do something with pipedText or the args
}
CodeMiller
  • 256
  • 2
  • 4
  • 1
    the answer here by hans passant http://stackoverflow.com/questions/3453220/how-to-detect-if-console-in-stdin-has-been-redirected near the end, mentions an even better way `System.Console.WriteLine(System.Console.IsInputRedirected.ToString());` – barlop Oct 19 '16 at 00:07
15

in .NET 4.5 it's

if (Console.IsInputRedirected)
{
    using(stream s = Console.OpenStandardInput())
    {
        ...
gordy
  • 9,360
  • 1
  • 31
  • 43
10

This is the way to do it:

static void Main(string[] args)
{
    Console.SetIn(new StreamReader(Console.OpenStandardInput(8192))); // This will allow input >256 chars
    while (Console.In.Peek() != -1)
    {
        string input = Console.In.ReadLine();
        Console.WriteLine("Data read was " + input);
    }
}

This allows two usage methods. Read from standard input:

C:\test>myProgram.exe
hello
Data read was hello

or read from piped input:

C:\test>echo hello | myProgram.exe
Data read was hello
matt burns
  • 24,742
  • 13
  • 105
  • 107
4

Here is another alternate solution that was put together from the other solutions plus a peek().

Without the Peek() I was experiencing that the app would not return without ctrl-c at the end when doing "type t.txt | prog.exe" where t.txt is a multi-line file. But just "prog.exe" or "echo hi | prog.exe" worked fine.

this code is meant to only process piped input.

static int Main(string[] args)
{
    // if nothing is being piped in, then exit
    if (!IsPipedInput())
        return 0;

    while (Console.In.Peek() != -1)
    {
        string input = Console.In.ReadLine();
        Console.WriteLine(input);
    }

    return 0;
}

private static bool IsPipedInput()
{
    try
    {
        bool isKey = Console.KeyAvailable;
        return false;
    }
    catch
    {
        return true;
    }
}
Matthew Benedict
  • 1,071
  • 2
  • 7
  • 4
  • 2
    the answer here by hans passant http://stackoverflow.com/questions/3453220/how-to-detect-if-console-in-stdin-has-been-redirected near the end, mentions an even better way `System.Console.WriteLine(System.Console.IsInputRedirected.ToString());` – barlop Oct 19 '16 at 00:09
3

This will also work for

c:\MyApp.exe < input.txt

I had to use a StringBuilder to manipulate the inputs captured from Stdin:

public static void Main()
{
    List<string> salesLines = new List<string>();
    Console.InputEncoding = Encoding.UTF8;
    using (StreamReader reader = new StreamReader(Console.OpenStandardInput(), Console.InputEncoding))
    {
        string stdin;
        do
        {
            StringBuilder stdinBuilder = new StringBuilder();
            stdin = reader.ReadLine();
            stdinBuilder.Append(stdin);
            var lineIn = stdin;
            if (stdinBuilder.ToString().Trim() != "")
            {
                salesLines.Add(stdinBuilder.ToString().Trim());
            }

        } while (stdin != null);

    }
}
roelofs
  • 2,132
  • 20
  • 25
Si Zi
  • 1,109
  • 10
  • 6
2

Console.In is a reference to a TextReader wrapped around the standard input stream. When piping large amounts of data to your program, it might be easier to work with that way.

Joel Mueller
  • 28,324
  • 9
  • 63
  • 88
1

there is a problem with supplied example.

  while ((s = Console.ReadLine()) != null)

will stuck waiting for input if program was launched without piped data. so user has to manually press any key to exit program.

Alex N
  • 46
  • 4