Skip to content

Instantly share code, notes, and snippets.

@ryansroberts
Created December 11, 2013 17:23
Show Gist options
  • Save ryansroberts/7914692 to your computer and use it in GitHub Desktop.
Save ryansroberts/7914692 to your computer and use it in GitHub Desktop.
public class AsyncStreamCopier
{
public event EventHandler Completed;
private readonly Stream input;
private readonly Stream output;
private byte[] buffer = new byte[4096];
public AsyncStreamCopier(Stream input, Stream output)
{
this.input = input;
this.output = output;
}
public void Start()
{
GetNextChunk();
}
private void GetNextChunk()
{
input.BeginRead(buffer, 0, buffer.Length, InputReadComplete, null);
}
private void InputReadComplete(IAsyncResult ar)
{
int bytesRead = input.EndRead(ar);
if (bytesRead == 0)
{
RaiseCompleted();
return;
}
// write synchronously
output.Write(buffer, 0, bytesRead);
GetNextChunk();
}
private void RaiseCompleted()
{
if (Completed != null)
{
Completed(this, EventArgs.Empty);
}
}
}
public class ProcessOutputReader
{
private readonly Process process;
private readonly Stream ostr;
private MemoryStream errorStream;
private AsyncStreamCopier stdErrorReader;
private AsyncStreamCopier stdOutReader;
public string StdError()
{
errorStream.Seek(0, SeekOrigin.Begin);
return new StreamReader(errorStream).ReadToEnd();
}
public ProcessOutputReader(Process process, Stream ostr)
{
if (process == null)
{
throw new ArgumentNullException("process");
}
process.EnableRaisingEvents = true;
this.process = process;
this.stdErrorReader = new AsyncStreamCopier(process.StandardError.BaseStream,errorStream = new MemoryStream());
this.stdOutReader = new AsyncStreamCopier(process.StandardOutput.BaseStream, this.ostr = ostr);
}
/// <summary>
/// Checks that the process is running.
/// </summary>
private void CheckProcessRunning()
{
if (this.process.HasExited)
{
throw new InvalidOperationException("Process has exited");
}
}
public void ReadProcessOutput()
{
CheckProcessRunning();
stdErrorReader.Start();
stdOutReader.Start();
process.Exited += (e, v) =>
{
process.StandardOutput.BaseStream.CopyTo(ostr);
process.StandardError.BaseStream.CopyTo(errorStream);
};
process.WaitForExit();
}
}
Use:
var reader = new ProcessOutputReader(process, output);
var bytes = new UTF8Encoding().GetBytes(xmlInput);
process.StandardInput.BaseStream.Write(bytes, 0, bytes.Length);
process.StandardInput.Close();
reader.ReadProcessOutput();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment