J
jpalmer
Hi,
I would like to implement some c# .NET 2.0 code that pipes an input .NET
stream into an external process and then captures the process’s stdout and
stderr into.NET streams. I was wondering what the best way to do this is.
My current thinking is to use threads to implement the reading and writing
streams in parallel. However starting all of these threads seems quite a lot
of overhead for such a simple task.
The basic sort of thing I trying to do as run on the command line looks like
this (using a command line utility called crx2rnx):
cat infile | crx2rnx - > outfile.
Note that running this command works and no data is output on the stderr.
Here's my attempt at the code using threads. This current implementation
runs but the the thread that is running the WriteProcStdOut() method does not
complete. It seems to be locked on the "while (stdout.Read(buf, 0, bufSize) >
0)" method call.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Threading;
public class Program
{
private static Process _process;
private static FileStream _inputStream;
private static FileStream _outputStream;
public static void Main(string[] args)
{
string compactFile = "infile";
string outputRinexFile = "outfile";
try
{
_inputStream = new FileStream(
compactFile, FileMode.Open, FileAccess.Read);
_outputStream = new FileStream(
outputRinexFile, FileMode.Create, FileAccess.Write);
_process = new Process();
_process.StartInfo.FileName = "crx2rnx";
_process.StartInfo.Arguments = "-";
_process.StartInfo.RedirectStandardOutput = true;
_process.StartInfo.RedirectStandardInput = true;
_process.StartInfo.UseShellExecute = false;
_process.StartInfo.CreateNoWindow = true;
_process.Start();
new Thread(new ThreadStart(ReadProcStdIn)).Start();
new Thread(new ThreadStart(WriteProcStdOut)).Start();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static void ReadProcStdIn()
{
try
{
const int bufSize = 1024;
byte[] buf = new byte[bufSize];
Stream stdin = _process.StandardInput.BaseStream;
while (_inputStream.Read(buf, 0, bufSize) > 0)
{
stdin.Write(buf, 0, bufSize);
}
}
catch (Exception e)
{
Console.Error.WriteLine("Error Writing to process stdin:"
+ e.Message);
}
}
private static void WriteProcStdOut()
{
try
{
const int bufSize = 1024;
byte[] buf = new byte[bufSize];
Stream stdout = _process.StandardOutput.BaseStream;
while (stdout.Read(buf, 0, bufSize) > 0)
{
_outputStream.Write(buf, 0, bufSize);
}
}
catch (Exception e)
{
Console.Error.WriteLine("ShowProcStdOut:" + e.Message);
}
}
}
Initially I thought that the "crx2rnx" process was not flushing its stdout.
However I have access to the program's C source code as was able to ensure
that a fflush() call was made before the process ended. So I'm currently not
sure where to go from here...
Thanks
Jeremy
I would like to implement some c# .NET 2.0 code that pipes an input .NET
stream into an external process and then captures the process’s stdout and
stderr into.NET streams. I was wondering what the best way to do this is.
My current thinking is to use threads to implement the reading and writing
streams in parallel. However starting all of these threads seems quite a lot
of overhead for such a simple task.
The basic sort of thing I trying to do as run on the command line looks like
this (using a command line utility called crx2rnx):
cat infile | crx2rnx - > outfile.
Note that running this command works and no data is output on the stderr.
Here's my attempt at the code using threads. This current implementation
runs but the the thread that is running the WriteProcStdOut() method does not
complete. It seems to be locked on the "while (stdout.Read(buf, 0, bufSize) >
0)" method call.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Threading;
public class Program
{
private static Process _process;
private static FileStream _inputStream;
private static FileStream _outputStream;
public static void Main(string[] args)
{
string compactFile = "infile";
string outputRinexFile = "outfile";
try
{
_inputStream = new FileStream(
compactFile, FileMode.Open, FileAccess.Read);
_outputStream = new FileStream(
outputRinexFile, FileMode.Create, FileAccess.Write);
_process = new Process();
_process.StartInfo.FileName = "crx2rnx";
_process.StartInfo.Arguments = "-";
_process.StartInfo.RedirectStandardOutput = true;
_process.StartInfo.RedirectStandardInput = true;
_process.StartInfo.UseShellExecute = false;
_process.StartInfo.CreateNoWindow = true;
_process.Start();
new Thread(new ThreadStart(ReadProcStdIn)).Start();
new Thread(new ThreadStart(WriteProcStdOut)).Start();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static void ReadProcStdIn()
{
try
{
const int bufSize = 1024;
byte[] buf = new byte[bufSize];
Stream stdin = _process.StandardInput.BaseStream;
while (_inputStream.Read(buf, 0, bufSize) > 0)
{
stdin.Write(buf, 0, bufSize);
}
}
catch (Exception e)
{
Console.Error.WriteLine("Error Writing to process stdin:"
+ e.Message);
}
}
private static void WriteProcStdOut()
{
try
{
const int bufSize = 1024;
byte[] buf = new byte[bufSize];
Stream stdout = _process.StandardOutput.BaseStream;
while (stdout.Read(buf, 0, bufSize) > 0)
{
_outputStream.Write(buf, 0, bufSize);
}
}
catch (Exception e)
{
Console.Error.WriteLine("ShowProcStdOut:" + e.Message);
}
}
}
Initially I thought that the "crx2rnx" process was not flushing its stdout.
However I have access to the program's C source code as was able to ensure
that a fflush() call was made before the process ended. So I'm currently not
sure where to go from here...
Thanks
Jeremy