There are many options in .NET for interprocess communication. If you own one process that is starting another, you can use console I/O as a minimalist IPC.
This approach only works if your own code is launching the other process. There is no convenient way to attach to an already running process and redirect it’s standard I/O in .NET. The child process needs to be something that already uses console I/O or something you can modify.
The parent and child process can either be a GUI or Console application (any mix). Standard and Core .NET are supported.
If these limitations are too restrictive, consider the NamedPipeServerStream as the next step up or review the broader set of IPC options in Windows.
Starting the Process
ProcessStartInfo startInfo = new ProcessStartInfo(path); startInfo.UseShellExecute = false; // required to redirect I/O startInfo.RedirectStandardInput = true; startInfo.RedirectStandardOutput = true; Process process = Process.Start(startInfo);
If the child is a console application, it can be useful to add this line to hide the console window:
startInfo.CreateNoWindow = true;
Side Note: Access Denied
If you accidentally try to use a directory path when calling
Process.Start, you will get a
Win32 AccessDenied exception. This is misleading since no amount of Administrator permission will solve it. It may help your sanity to check
Directory.Exists(path) and throw your own exception before calling
You have the option of synchronous or asynchronous communication. This choice can be made independently for the parent and child process. Consider isolating all of this in a shared library so that both parent and child processes only see plain old C# method calls.
Remember that the child process is not required to be a Console project in order to use
Console class methods.
If I am already running in another thread I will tend toward the simplicity of synchronous calls. The
ReadLine method will block until data is received. Also beware that
WriteLine can block if the child application’s receive buffer is full.
// From the parent process _process.StandardInput.WriteLine("Hello from parent"); string line = _process.StandardOutput.ReadLine(); // From the child process string line = Console.ReadLine(); Console.WriteLine("Echo " + line);
Async from the parent process is straightforward:
// From the parent process await _process.StandardInput.WriteLineAsync("Async hello from parent"); string line = await _process.StandardOutput.ReadLineAsync();
But there are no read/write async methods on the
Console class so we have to wrap them with
// From the child process string line = await Task.Run(() => Console.ReadLine()); await Task.Run(() => Console.WriteLine("Echo " + line));
You will need to select C# 7.1 or higher to use an
async Main method within a Console project.
Featured Image Credit
Phidget SBC, photo by Nick Bushby