Skip to content

Instantly share code, notes, and snippets.

@antopor
Created March 7, 2015 04:14
Show Gist options
  • Save antopor/5515bed636c3d99395ea to your computer and use it in GitHub Desktop.
Save antopor/5515bed636c3d99395ea to your computer and use it in GitHub Desktop.
How to redirect Process' standart input/output (C#, .net 4.5, async code)
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace Test
{
class Program
{
static void Main(string[] args)
{
var cmd = new Process
{
StartInfo = new ProcessStartInfo("cmd.exe")
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true
}
};
cmd.Start();
StreamPipe pout = new StreamPipe(cmd.StandardOutput.BaseStream, Console.OpenStandardOutput());
StreamPipe perr = new StreamPipe(cmd.StandardError.BaseStream, Console.OpenStandardError());
StreamPipe pin = new StreamPipe(Console.OpenStandardInput(), cmd.StandardInput.BaseStream);
pin.Connect();
pout.Connect();
perr.Connect();
cmd.WaitForExit();
}
}
class StreamPipe
{
private const Int32 BufferSize = 4096;
public Stream Source { get; protected set; }
public Stream Destination { get; protected set; }
private CancellationTokenSource _cancellationToken;
private Task _worker;
public StreamPipe(Stream source, Stream destination)
{
Source = source;
Destination = destination;
}
public StreamPipe Connect()
{
_cancellationToken = new CancellationTokenSource();
_worker = Task.Run(async () =>
{
byte[] buffer = new byte[BufferSize];
while (true)
{
_cancellationToken.Token.ThrowIfCancellationRequested();
var count = await Source.ReadAsync(buffer, 0, BufferSize, _cancellationToken.Token);
if (count <= 0)
break;
await Destination.WriteAsync(buffer, 0, count, _cancellationToken.Token);
await Destination.FlushAsync(_cancellationToken.Token);
}
}, _cancellationToken.Token);
return this;
}
public void Disconnect()
{
_cancellationToken.Cancel();
}
}
}
@christopherQWER
Copy link

Please, tell me, how could I do the same thing with the .Net 3.5 (without Threading.Tasks)? Thank you in advance.

@cybertech99
Copy link

Any chance you can show how I would implement this in a win forms where the output is piped to a richtextbox and the input is from a textbox?

@KoalaBear84
Copy link

Wow, this is a nice and simple way which works quite well, except when Console.ReadKey() is used in the running application.

If anybody has an idea how that could work, that would be nice. I do understand that this maybe is technically not possible.

@ddelapasse2
Copy link

@KoalaBear84, did you resolve this? Having the same issue with my outer loops ReadKey aborting when my Process "redirection" completes.

@KoalaBear84
Copy link

@ddelpasse2 No, looks like I didn't, have used it in 3 projects, and ReadKey doesn't work. I'm curious how they make it work in Windows Terminal, where it works as expected.

@seikosantana
Copy link

Cool!

I'm trying to achieve this on Ubuntu, redirecting streams from and to bash, but
When executing a sudo command, with the password prompt, the password we typed in is partially visible (some characters are shown) and even if we typed in correctly, it will just send to the sudo prompt what is shown.

And any echos on the shell (like our current location) each time command is prompted, is not printed to the console.

Any clue what's going on?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment