c# process iostream io-redirection

c# - Redirigir la entrada estándar de la aplicación de la consola



process iostream (2)

Aquí hay una clase que he escrito para manejar ese tipo de cosas. Sientase libre de usarlo. Su propósito es iniciar una aplicación de consola y "hablar" con ella. También tiene la capacidad de recibir resultados. Buena suerte.

using System; using System.Diagnostics; using System.Text; using System.Threading; using System.Threading.Tasks; public class ConsoleAppManager { private readonly string appName; private readonly Process process = new Process(); private readonly object theLock = new object(); private SynchronizationContext context; private string pendingWriteData; public ConsoleAppManager(string appName) { this.appName = appName; this.process.StartInfo.FileName = this.appName; this.process.StartInfo.RedirectStandardError = true; this.process.StartInfo.StandardErrorEncoding = Encoding.UTF8; this.process.StartInfo.RedirectStandardInput = true; this.process.StartInfo.RedirectStandardOutput = true; this.process.EnableRaisingEvents = true; this.process.StartInfo.CreateNoWindow = true; this.process.StartInfo.UseShellExecute = false; this.process.StartInfo.StandardOutputEncoding = Encoding.UTF8; this.process.Exited += this.ProcessOnExited; } public event EventHandler<string> ErrorTextReceived; public event EventHandler ProcessExited; public event EventHandler<string> StandartTextReceived; public int ExitCode { get { return this.process.ExitCode; } } public bool Running { get; private set; } public void ExecuteAsync(params string[] args) { if (this.Running) { throw new InvalidOperationException( "Process is still Running. Please wait for the process to complete."); } string arguments = string.Join(" ", args); this.process.StartInfo.Arguments = arguments; this.context = SynchronizationContext.Current; this.process.Start(); this.Running = true; new Task(this.ReadOutputAsync).Start(); new Task(this.WriteInputTask).Start(); new Task(this.ReadOutputErrorAsync).Start(); } public void Write(string data) { if (data == null) { return; } lock (this.theLock) { this.pendingWriteData = data; } } public void WriteLine(string data) { this.Write(data + Environment.NewLine); } protected virtual void OnErrorTextReceived(string e) { EventHandler<string> handler = this.ErrorTextReceived; if (handler != null) { if (this.context != null) { this.context.Post(delegate { handler(this, e); }, null); } else { handler(this, e); } } } protected virtual void OnProcessExited() { EventHandler handler = this.ProcessExited; if (handler != null) { handler(this, EventArgs.Empty); } } protected virtual void OnStandartTextReceived(string e) { EventHandler<string> handler = this.StandartTextReceived; if (handler != null) { if (this.context != null) { this.context.Post(delegate { handler(this, e); }, null); } else { handler(this, e); } } } private void ProcessOnExited(object sender, EventArgs eventArgs) { this.OnProcessExited(); } private async void ReadOutputAsync() { var standart = new StringBuilder(); var buff = new char[1024]; int length; while (this.process.HasExited == false) { standart.Clear(); length = await this.process.StandardOutput.ReadAsync(buff, 0, buff.Length); standart.Append(buff.SubArray(0, length)); this.OnStandartTextReceived(standart.ToString()); Thread.Sleep(1); } this.Running = false; } private async void ReadOutputErrorAsync() { var sb = new StringBuilder(); do { sb.Clear(); var buff = new char[1024]; int length = await this.process.StandardError.ReadAsync(buff, 0, buff.Length); sb.Append(buff.SubArray(0, length)); this.OnErrorTextReceived(sb.ToString()); Thread.Sleep(1); } while (this.process.HasExited == false); } private async void WriteInputTask() { while (this.process.HasExited == false) { Thread.Sleep(1); if (this.pendingWriteData != null) { await this.process.StandardInput.WriteLineAsync(this.pendingWriteData); await this.process.StandardInput.FlushAsync(); lock (this.theLock) { this.pendingWriteData = null; } } } } }

Tengo una aplicación de consola que estoy tratando de automatizar mediante la redirección del flujo de entrada estándar del proceso. En modo manual después de abrir la aplicación, espera la entrada del usuario como a continuación,

Creé el proceso con la secuencia de entrada estándar redirigida. El fragmento de código es el siguiente,

Process newProcess = new Process(); newProcess.StartInfo.FileName = exeName; newProcess.StartInfo.Arguments = argsLine; newProcess.StartInfo.UseShellExecute = false; newProcess.StartInfo.RedirectStandardOutput = false ; newProcess.StartInfo.CreateNoWindow = false; newProcess.StartInfo.RedirectStandardInput = true; newProcess.Start();

Pero crear un proceso como este da un ciclo infinito que se muestra a continuación,

Es como si estuviera enviando el comando de tecla Enter continuamente al flujo de entrada del proceso. ¿Alguien puede señalarme qué estoy haciendo mal aquí?

Del mismo modo, la redirección de flujo de salida estándar tampoco funciona después de hacer

newProcess.StartInfo.RedirectStandardOutput = true

Pero puedo manejar eso.

¿El redireccionamiento de las transmisiones estándar funciona con todas las aplicaciones de la consola o existe alguna excepción?


Siguiendo la respuesta anterior, solo agregaré el método de extensión de SubArray, solo en caso de que agregue esta clase a su código donde no está anidado dentro de ninguna clase (el código no parecía legible en un comentario, así que lo agregué aquí)

public static class CharArrayExtensions { public static char[] SubArray(this char[] input,int startIndex, int length) { List<char> result= new List<char>(); for (int i = startIndex; i < length; i++) { result.Add(input[i]); } return result.ToArray(); } }