2011-08-19 7 views
5

Estoy escribiendo una aplicación de formato C# que inicia un segundo proceso para ejecutar comandos de shell como "dir" y "ping". Redirijo la salida del segundo proceso para que mi aplicación pueda recibir el resultado del comando. Funciona aproximadamente bien.C#: obtener el resultado del comando de shell externo por línea

El único problema es que mi aplicación winform recibe el resultado de la línea de comandos como un todo en lugar de línea por línea. Por ejemplo, tiene que esperar a que finalice el comando externo "ping" (que toma muchos segundos o más) y luego recibe toda la salida (muchas líneas) a la vez.

Lo que quiero es que la aplicación reciba la salida de cmdline en tiempo real, es decir, por líneas no por bloque. ¿Es esto factible?

Estoy usando este código para leer la salida: tiempo (! (Resultado = proc.StandardOutput.ReadLine()) = null)

Pero no funciona de la manera que esperaba. Gracias de antemano.

EDIT: Aquí está el código que estoy utilizando:

System.Diagnostics.ProcessStartInfo procStartInfo = new 
      System.Diagnostics.ProcessStartInfo("cmd", "/c " + command); 

    procStartInfo.WindowStyle = ProcessWindowStyle.Hidden; 

    // The following commands are needed to redirect the standard output. 
    procStartInfo.RedirectStandardOutput = true; 
    procStartInfo.UseShellExecute = false; 
    procStartInfo.CreateNoWindow = true; 
    // Now we create a process, assign its ProcessStartInfo and start it 
    System.Diagnostics.Process proc = new System.Diagnostics.Process(); 
    proc.StartInfo = procStartInfo; 
    proc.Start(); 

    // Get the output into a string 
    string result; 
    try { 
     while ((result = proc.StandardOutput.ReadLine()) != null) 
     { 
      AppendRtfText(result+"\n", Brushes.Black); 
     } 
    } // here I expect it to update the text box line by line in real time 
     // but it does not. 
+1

[posible duplicado] (http://stackoverflow.com/questions/ 415620/redirect-console-output-to-textbox-in-separate-program-c) –

+0

Mostrar el código que ha intentado será útil. –

Respuesta

3

Eche un vistazo al ejemplo en this msdn article sobre cómo hacer la lectura completamente asíncrona.

Más allá de eso espero que el código hace que leer línea por línea, pero ahora la interfaz de usuario no recibe cualquier momento para volver a pintar (Application.DoEvents falta(); después de actualizar el RTFTextBox

+0

Gracias @Eddy, tienes razón. Pero DoEvents() no está disponible en WPF. Usé esta solución: http://stackoverflow.com/questions/4502037/where-is-the-application-doevents-in-wpf – Charlie

2

En lugar de bucle que utiliza while ((result = proc.StandardOutput.ReadLine()) != null) usted debe de utilizar:

... 
proc.OutputDataReceived += proc_DataReceived; 
proc.Start(); 
proc.BeginOutputReadLine(); 
proc.WaitForExit(); 

Esto iniciará asíncrono lectura de las líneas cuando llega, se luego maneje las líneas leídas por e.Data en el controlador proc_DataReceived, ya que se usa BeginOutputReadline el e.Data será una línea de cadena.

0

que tenían el mismo problema y tiene alrededor de ella con el siguiente. he encontrado que si tuviera un error en la aplicación externa que estaba recibiendo ninguna salida en absoluto el uso el método ReadToEnd(), por lo que se cambió para usar el lector de línea por línea. Se cambiará para usar la respuesta provista por Saa'd, ya que se ve como la forma correcta de manejarlo.

encuentra también esta solución: c# coding convention public/private contexts que proporciona para el manejo de error al mismo tiempo y dar una explicación más completa a la utilización de externalApp.OutputDataReceived += (sender, args) => Console.WriteLine(args.Data);

Process externalApp = new Process(); 
     externalApp.StartInfo.FileName = config.ExternalApps + @"\location\DeleteApp.exe"; 
     externalApp.StartInfo.Arguments = Directory.GetCurrentDirectory() + @"\..\..\..\project\argumentsForDeleteApp.xml"; 
     externalApp.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; 
     externalApp.StartInfo.UseShellExecute = false; 
     externalApp.StartInfo.RedirectStandardOutput = true; 
     Console.Out.WriteLine(DateTime.UtcNow.ToLocalTime().ToString() + 
      ":###### External app: " + externalApp.StartInfo.FileName + " -  START"); 
     externalApp.Start(); 
     using (StreamReader reader = externalApp.StandardOutput) 
     { 
      while (!reader.EndOfStream) 
      { 
       string result = reader.ReadLine(); 
       Console.Out.WriteLine(result); 
      } 
     } 
     externalApp.WaitForExit(); 
Cuestiones relacionadas