Pregunta

Tengo una aplicación GUI dentro de la cual estoy generando una aplicación de consola utilizando la clase Process.

Process p1 = new Process();
p1.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p1.StartInfo.CreateNoWindow = true;
p1.StartInfo.UseShellExecute = false;
p1.StartInfo.FileName = Path.Combine(basepath, "abc.exe");
p1.StartInfo.Arguments = "/pn abc.exe /f \"temp1.txt\"";
p1.StartInfo.RedirectStandardError = true;
p1.StartInfo.RedirectStandardInput = true;
p1.StartInfo.RedirectStandardOutput = true;
p1.OutputDataReceived += new DataReceivedEventHandler(outputreceived);
p1.ErrorDataReceived += new DataReceivedEventHandler(errorreceived);
p1.Start();
tocmd = p1.StandardInput;
p1.BeginOutputReadLine();
p1.BeginErrorReadLine();

Ahora tengo un problema que, a pesar de que lee la salida de la consola de forma asíncrona pero parece desencadenar el evento solo cuando el búfer interno se llena con cierta cantidad. Quiero que muestre los datos como vienen. Si hay 10 bytes en el búfer, deja que muestre los 10 bytes. Mi programa implementa la llamada a sleep () internamente, así que necesito imprimir los datos hasta que se duerma.

¿Cómo puedo hacerlo?

=============

Como se mencionó, la salida tiene búfer de línea, probé el siguiente cambio en el código

p1.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p1.StartInfo.CreateNoWindow = true;
p1.StartInfo.UseShellExecute = false;
p1.StartInfo.FileName = Path.Combine(basepath, "abc.exe");
p1.StartInfo.Arguments = pnswitch + " /f \"temp1.txt\"";
p1.StartInfo.RedirectStandardError = false;
p1.StartInfo.RedirectStandardInput = true;
p1.StartInfo.RedirectStandardOutput = true;
p1.Start();
tocmd = p1.StandardInput;
MethodInvoker mi = new MethodInvoker(readout);
mi.BeginInvoke(null, p1);

y la lectura interna que escribí

void readout()
    {
        string str;
        while ((str = p1.StandardOutput.ReadLine()) != null)
        {
            richTextBox1.Invoke(new UpdateOutputCallback(this.updateoutput), new object[] { str });
            p1.StandardOutput.BaseStream.Flush();
        }
    }

Entonces, creo que ahora se supervisa cuando se escribe cada línea y se imprime, ¿no? Esto tampoco funcionó. ¿Hay algo mal allí?

¿Fue útil?

Solución

Los datos de salida y de error recibidos están en búfer de línea y solo se activarán cuando se agregue una nueva línea.

Su mejor apuesta es usar su propio lector que puede leer la entrada, byte por byte. Obviamente, esto debería ser sin bloqueo :)

Otros consejos

Para lograr esto, debe usar operaciones de lectura síncrona en una secuencia redirigida. Su código se vería así (Ejemplo de MSDN):

// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "Write500Lines.exe";
p.Start();
// Do not wait for the child process to exit before
// reading to the end of its redirected stream.
// p.WaitForExit();
// Read the output stream first and then wait.
**string output = p.StandardOutput.ReadToEnd();**
p.WaitForExit();

Para lograr un comportamiento asíncrono, deberías usar algunos subprocesos.

Artículo de MSDN aquí

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top