Reindirizza l’output della console alla casella di testo in un programma separato

Sto sviluppando un’applicazione Windows Form che mi richiede di chiamare un programma separato per eseguire un’attività. Il programma è un’applicazione console e devo redirect lo standard output dalla console a un TextBox nel mio programma.

Non ho problemi a eseguire il programma dalla mia applicazione, ma non so come redirect l’output alla mia applicazione. Ho bisogno di catturare l’output mentre il programma è in esecuzione utilizzando eventi.

Il programma della console non intende arrestarsi finché la mia applicazione non si arresta e il testo cambia costantemente ad intervalli casuali. Quello che sto tentando di fare è semplicemente l’output di hook dalla console per triggersre un gestore di eventi che può quindi essere utilizzato per aggiornare il TextBox.

Sto usando C # per codificare il programma e utilizzare il framework .NET per lo sviluppo. L’applicazione originale non è un programma .NET.

EDIT: Ecco il codice di esempio di ciò che sto cercando di fare. Nella mia app finale, sostituirò Console.WriteLine con il codice per aggiornare il TextBox. Ho provato a impostare un breakpoint nel mio gestore di eventi e non è nemmeno raggiunto.

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); } 

Questo funziona per me:

 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 } 

Puoi usare il seguente codice

  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(); 

Ho aggiunto un certo numero di metodi di supporto alla piattaforma O2 (progetto Open Source) che consente di creare facilmente un’interazione con un altro processo tramite l’output e l’input della console (vedi http://code.google.com/p/o2platform/ source / browse / trunk / O2_Scripts / APIs / Windows / CmdExe / CmdExeAPI.cs )

Utile anche per te potrebbe essere l’API che consente la visualizzazione dell’output della console del processo corrente (in un controllo esistente o finestra popup). Vedi questo post sul blog per maggiori dettagli: http://o2platform.wordpress.com/2011/11/26/api_consoleout-cs-inprocess-capture-of-the-console-output/ (questo blog contiene anche dettagli su come consumare l’output della console di nuovi processi)

Grazie a Marc Maxham per la sua risposta che mi fa risparmiare tempo!

Come Jon di All Trades lo nota, UseShellExecute deve essere impostato su false per redirect i flussi IO, altrimenti la chiamata Start () genera una InvalidOperationException.

Ecco la mia modifica del codice in cui txtOut è un WPF readonly Textbox

  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) )); }