T
Tony Freixas
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 + "\" ";
}
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);
}
}
}
}
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 + "\" ";
}
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);
}
}
}
}