Pregunta

Estoy desarrollando una aplicación de formularios Windows Forms que requiere que llame a un programa separado para realizar una tarea. El programa es una aplicación de consola y necesito redirigir la salida estándar de la consola a un TextBox en mi programa.

No tengo problemas para ejecutar el programa desde mi aplicación, pero no sé cómo redirigir la salida a mi aplicación. Necesito capturar la salida mientras el programa se está ejecutando usando eventos.

El programa de consola no debe dejar de ejecutarse hasta que mi aplicación se detenga y el texto cambie constantemente a intervalos aleatorios. Lo que intento hacer es simplemente conectar la salida de la consola para activar un controlador de eventos que luego se puede usar para actualizar TextBox.

Estoy usando C # para codificar el programa y estoy usando el marco .NET para el desarrollo. La aplicación original no es un programa .NET.

EDITAR: Aquí hay un código de ejemplo de lo que estoy tratando de hacer. En mi aplicación final, reemplazaré Console.WriteLine con código para actualizar TextBox. Traté de establecer un punto de interrupción en mi controlador de eventos, y ni siquiera se alcanza.

    void Method()
    {
        var p = new Process();
        var path = @"C:\ConsoleApp.exe";

        p.StartInfo.FileName = path;
        p.StartInfo.UseShellExecute = false;
        p.OutputDataReceived += p_OutputDataReceived;

        p.Start();
    }

    static void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        Console.WriteLine(">>> {0}", e.Data);
    }
¿Fue útil?

Solución

Esto funciona para mí:

void RunWithRedirect(string cmdPath)
{
    var proc = new Process();
    proc.StartInfo.FileName = cmdPath;

    // set up output redirection
    proc.StartInfo.RedirectStandardOutput = true;
    proc.StartInfo.RedirectStandardError = true;    
    proc.EnableRaisingEvents = true;
    proc.StartInfo.CreateNoWindow = true;
    // see below for output handler
    proc.ErrorDataReceived += proc_DataReceived;
    proc.OutputDataReceived += proc_DataReceived;

    proc.Start();

    proc.BeginErrorReadLine();
    proc.BeginOutputReadLine();

    proc.WaitForExit();
}

void proc_DataReceived(object sender, DataReceivedEventArgs e)
{
    // output will be in string e.Data
}

Otros consejos

Puedes usar el siguiente código

        MemoryStream mem = new MemoryStream(1000);
        StreamWriter writer = new StreamWriter(mem);
        Console.SetOut(writer);

        Assembly assembly = Assembly.LoadFrom(@"C:\ConsoleApp.exe");
        assembly.EntryPoint.Invoke(null, null);
        writer.Close();

        string s = Encoding.Default.GetString(mem.ToArray());
        mem.Close();

He agregado una serie de métodos auxiliares a Plataforma O2 (proyecto de código abierto) que le permiten escribir fácilmente un script interacción con otro proceso a través de la salida y la entrada de la consola (consulte http://code.google.com/p/o2platform/source/browse/trunk/O2_Scripts/APIs/Windows/CmdExe/CmdExeAPI.cs )

También útil para usted podría ser la API que permite ver la salida de la consola del proceso actual (en un control existente o ventana emergente). Consulte esta publicación de blog para obtener más detalles: http://o2platform.wordpress.com/2011/11/26/api_consoleout-cs-inprocess-capture-of-the-console-output/ (este blog también contiene detalles sobre cómo consumir la consola salida de nuevos procesos)

¡Gracias a Marc Maxham por su respuesta que me ahorra tiempo!

Como Jon of All Trades lo nota, UseShellExecute debe establecerse en falso para redirigir las secuencias de E / S; de lo contrario, la llamada Start () arroja una InvalidOperationException .

Aquí está mi modificación del código donde txtOut es un cuadro de texto de solo lectura de WPF

void RunWithRedirect(string cmdargs)
{
    var proc = new Process()
    {
        StartInfo = new ProcessStartInfo("cmd.exe", "/k " + cmdargs)
        {
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            CreateNoWindow = true
        },
        EnableRaisingEvents = true
    };

    // see below for output handler
    proc.ErrorDataReceived += proc_DataReceived;
    proc.OutputDataReceived += proc_DataReceived;
    proc.Start();

    proc.BeginErrorReadLine();
    proc.BeginOutputReadLine();

    proc.WaitForExit();
}

void proc_DataReceived(object sender, DataReceivedEventArgs e)
{
    if (e.Data != null)
        Dispatcher.BeginInvoke(new Action( () => txtOut.Text += (Environment.NewLine + e.Data) ));
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top