49

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?

9 Answers 9

54

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>
Sign up to request clarification or add additional context in comments.

7 Comments

Does your example works for : echo "Foo bar baz" | ConsoleApplication1.exe | ConsoleApplication1.exe ?
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.
If you're working with binary data: stackoverflow.com/questions/1562417/…
why check for ReadLine == null, does it ever return null? (Wouldn't it return empty string if nothing is entered). stackoverflow.com/questions/26338571/…
@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: msdn.microsoft.com/de-de/library/…
|
21

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
}

1 Comment

the answer here by hans passant stackoverflow.com/questions/3453220/… near the end, mentions an even better way System.Console.WriteLine(System.Console.IsInputRedirected.ToString());
16

in .NET 4.5 it's

if (Console.IsInputRedirected)
{
    using(stream s = Console.OpenStandardInput())
    {
        ...

1 Comment

Hi, I can't seem to get it working with this code, any ideas?
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

Comments

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;
    }
}

1 Comment

the answer here by hans passant stackoverflow.com/questions/3453220/… near the end, mentions an even better way System.Console.WriteLine(System.Console.IsInputRedirected.ToString());
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);

    }
}

Comments

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.

Comments

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.

1 Comment

that is more worthy as a comment, and others have addressed that and a solution to it
0

This has become pretty simple nowadays. For .NET 10:

Check if anything has been piped with System.Console.IsInputRedirected. Get what's been piped with Sytem.Console.In.ReadToEnd(). Note that ReadToEnd will block your program forever(ish) if input isn't redirected. I'm fond of the method below to get piped input only if it's been given.

        public static string GetPipedInput()
        {
            return Console.IsInputRedirected
                ? Console.In.ReadToEnd()
                : string.Empty;
        }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.