Search code examples
c#console

Programmatically interacting with a console application


using System;
using System.Diagnostics;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        while (true)
        {
            Console.WriteLine("Menu");
            Console.WriteLine("====");
            Console.WriteLine("1. print \"Hello\"");
            Console.WriteLine("2. print \"world!\"");
            Console.WriteLine("3. write something to echo");
            Console.WriteLine("4. Quit");
            string str = Console.ReadLine();
            Console.WriteLine();

            char c = str.ToCharArray()[0];

            if (c == '1')
            {
                Console.WriteLine("Hello");
            }
            else if (c == '2')
            {
                Console.WriteLine(", world!");
            }
            else if (c == '3')
            {
                string input = Console.ReadLine();
                Console.WriteLine("{0}", input);
            }
            else if (c == '4')
            {
                break;
            }
        }
    }
}

Suppose, the above program compiles into main~1.exe.

Now, I have written another C# console application that will programmatically execute main~1.exe and let the user send inputs and return the output from the main~1.exe.

using System;
using System.Diagnostics;

class Program
{
    static void Main()
    {
        // Start the main~1.exe process
        Process process = new Process();
        process.StartInfo.FileName = "main~1.exe";
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.RedirectStandardInput = true;
        process.StartInfo.RedirectStandardOutput = true;
        process.Start();

        // Read and print the initial menu
        string menu = process.StandardOutput.ReadToEnd();
        Console.WriteLine(menu);

        // Loop to allow the user to send inputs and receive output
        while (true)
        {
            // Read the user's input
            string input = Console.ReadLine();

            // Write the input to the process's standard input stream
            process.StandardInput.WriteLine(input);

            // Read the process's output and print it to the console
            string output = process.StandardOutput.ReadToEnd();
            Console.WriteLine(output);
        }
    }
}

However, it is not working as expected.

the output screen doesn't show anything.

It doesn't show any sign that it is interacting with the main~1.exe.

What am I doing wrong in the second source code?


Solution

  • The issue is your main~1.exe is a long-running process and process.StandardOutput.ReadToEnd() will block you app because it's waiting for process exit.

    You need to use event on output received like this:

    ....
    process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
            {
                if (!string.IsNullOrEmpty(e.Data))
                {
                    Console.WriteLine(e.Data);
                }
            });
    
            process.Start();
    
            // Asynchronously read the standard output of the spawned process.
            // This raises OutputDataReceived events for each line of output.
            process.BeginOutputReadLine();
            
    
            // Loop to allow the user to send inputs and receive output
            while (true)
            {
                // Read the user's input
                string input = Console.ReadLine();
    
                // Write the input to the process's standard input stream
                process.StandardInput.WriteLine(input);
            }