Hello,
I'm trying to create a wrapper for a program. I want to execute
program 'X' by running program 'Y', such that 'Y' appears to function
pretty much like 'X' both in the way command line options are handled
and the way input, output and error messages are reported. Program 'X'
is a console application.
I had it pretty well figured out, I thought, until I ran into a case
where program X spit out ZIP code. In other words, I was reading
Process.StandardOutput.ReadLine() and writing to Console.WriteLine().
These don't handle binary output very well.
So I can read X's output using
Process.StandardOutput.BaseStream.ReadByte() but I can't find the
right method to write binary to Y's standard output. How do I convert
Console.Out to a StreamWriter? I want this to work efficiently, too.
Here's the program so far. Thanks for any suggestions.
using System;
using System.IO;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading;
namespace TigerHeron.CoreLib
{
public class ProgramExecute
{
public const int NONE = 0;
public const int REDIRECT_IO = 1;
private Process process;
public ProgramExecute(string[] args) : this(args, NONE)
{
}
public ProgramExecute(string[] args, int flags)
{
if (args.Length < 1) {
throw new ArgumentException("The array must have at least one
argument", "args");
}
process = new Process();
String program = args[0];
string newArgs = "";
for (int i = 1; i < args.Length; i++) {
newArgs += "\"" + args[i] + "\" ";
}
process.StartInfo.FileName = program;
process.StartInfo.Arguments = newArgs;
if ((flags & REDIRECT_IO) != 0) {
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
}
process.StartInfo.Verb = "Open";
process.StartInfo.UseShellExecute = (flags & REDIRECT_IO) == 0;
process.StartInfo.ErrorDialog = (flags & REDIRECT_IO) == 0;
process.StartInfo.CreateNoWindow = true;
process.Start();
if ((flags & REDIRECT_IO) != 0) {
new Thread(new ThreadStart(this.readStdin)).Start();
new Thread(new ThreadStart(this.readStdout)).Start();
new Thread(new ThreadStart(this.readStderr)).Start();
process.WaitForExit();
Environment.Exit(process.ExitCode);
}
}
private void readStdin()
{
try {
string line;
while ((line = Console.In.ReadLine()) != null) {
process.StandardInput.WriteLine(line);
}
}
catch (Exception e) {
Console.Error.WriteLine(e.Message);
}
}
private void readStdout()
{
try {
int b;
while ((b = process.StandardOutput.BaseStream.ReadByte()) != -1) {
Console.Write((char)b); // This doesn't work
}
}
catch (Exception e) {
Console.Error.WriteLine(e.Message);
}
}
private void readStderr()
{
try {
string line;
while ((line = process.StandardError.ReadLine()) != null) {
Console.Error.WriteLine(line);
}
}
catch (Exception e) {
Console.Error.WriteLine(e.Message);
}
}
}
}
Moty Michaely - 14 May 2007 06:07 GMT
> Hello,
>
[quoted text clipped - 114 lines]
>
> }
Dear Tony,
stdout/stdin can't output or input binary data. It's purpose is to
output/input charecters, depending on encoding settings.
Using BaseStream is not a good way since the StandardOutput is a
wrapper to the base stream. You can't be sure the wrapper doe's
exactly what the base stream does.
If you need to redirect binary data, you should use other methods to
achieve this purpose.