Pergunta

Estou desenvolvendo um aplicativo Windows Forms que me obriga a chamar um programa separado para executar uma tarefa. O programa é um aplicativo de console e eu preciso redirecionar a saída padrão do console para um TextBox no meu programa.

Não tenho nenhum problema executar o programa do meu aplicativo, mas eu não sei como redirecionar a saída para a minha candidatura. Eu preciso de saída de captura enquanto o programa está sendo executado usando eventos.

O programa de console não pretende parar de correr até que meu aplicativo pára eo texto muda constantemente em intervalos aleatórios. O que eu estou tentando fazer é simplesmente ligar a saída do console para acionar um manipulador de eventos que pode então ser usado para atualizar o TextBox.

Eu estou usando C # para o código do programa e usando o framework .NET para o desenvolvimento. O aplicativo original não é um programa .NET.

EDIT: Aqui é exemplo de código do que eu estou tentando fazer. Em meu aplicativo final, eu vou substituir Console.WriteLine com o código para atualizar o TextBox. Tentei definir um ponto de interrupção no meu manipulador de eventos, e nem sequer é alcançado.

    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);
    }
Foi útil?

Solução

Isso funciona para mim:

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
}

Outras dicas

Você pode usar o seguinte 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();

Eu adicionei uma série de métodos auxiliares para o Platform O2 (projeto Open Source) que permitem que você facilmente um script interacção com um outro processo através da saída e consola de entrada (ver http://code.google.com/p/o2platform/source/browse/trunk/O2_Scripts/APIs/Windows/CmdExe/CmdExeAPI.cs )

Também é útil para que você pode ser o API que permite a visualização da saída do console do processo atual (em uma janela do controle ou pop-up existente). Veja este post para mais detalhes: http://o2platform.wordpress.com/2011/11/26/api_consoleout-cs-inprocess-capture-of-the-console-output/ (este blog também contém detalhes de como consumir o console produção de novos processos)

Graças à Marc Maxham para sua resposta que me poupar tempo!

Como Jon of All Trades notar que, UseShellExecute deve ser definido como falso, a fim de redirecionar IO córregos, caso contrário, a chamada Start() lança uma InvalidOperationException.

Aqui está a minha modificação do código onde txtOut é um WPF somente leitura caixa de texto

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top