2010-01-06 18 views
11

Ich beginne eine Konsolenanwendung, aber wenn ich die Standardausgabe umleitung bekomme ich immer nichts!process.standardoutput.ReadToEnd() immer leer?

Wenn ich es nicht umleiten kann, und stellen Sie CreateNoWindow-false, sehe ich alles richtig in der Konsole, aber wenn ich es umleiten, kehrt StandardOutput.ReadToEnd() immer eine leere Zeichenfolge.

 Process cproc = new Process(); 
     cproc.StartInfo.CreateNoWindow = true; 
     cproc.StartInfo.FileName = Dest; 
     cproc.StartInfo.RedirectStandardOutput = true; 
     cproc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; 
     cproc.StartInfo.UseShellExecute = false; 
     cproc.EnableRaisingEvents = true; 
     cproc.Start(); 
     cproc.Exited += new EventHandler(cproc_Exited); 
     while(!stop) 
     { 
      result += cproc.StandardOutput.ReadToEnd(); 
     } 

The EventHandler cproc_exited setzt nur stop zu true. Kann jemand erklären, warum result immer string.Empty ist?

Antwort

7

Warum schleifen Sie? Sobald es bis zum Ende gelesen ist, wird es nicht mehr in der Lage sein, weitere Daten zu lesen, oder?

Sind Sie sicher, dass der Text tatsächlich in StandardOutput statt StandardError geschrieben wird?

(Und ja, natürlich wollen Sie RedirectStandardOutput auf true setzen, anstatt falsch ich davon aus, dass war nur ein Fall von Ihnen die falsche Version des Codes zu kopieren..)

EDIT: Wie ich in geraten habe Die Kommentare sollten Sie von Standardausgabe und Standardfehler in separaten Threads lesen. Do nicht warten, bis der Prozess beendet wurde - dies kann mit einem Deadlock enden, wo Sie auf den Prozess warten, aber der Prozess blockiert den Versuch, in stderr/stdout zu schreiben, weil Sie nicht aus dem gelesen haben Puffer.

Alternativ können Sie die Ereignisse OutputDataReceived und ErrorDataReceived abonnieren, um die Verwendung zusätzlicher Threads zu vermeiden.

+0

wenn ich es in während (! Stop) ändern { } s + = convproc.StandardOutput.ReadToEnd(); Ich bekomme einen Deadlock – alex

+0

heey, es funktioniert !! sieht aus wie mein Freund (der das Konsolenprogramm gemacht hat) es vermasselt hat! es schreibt alles in den Fehlerstrom !! Ich muss mit ihm reden, vielleicht kann er das reparieren. Danke für deine schnelle Antwort! Du hast mich davor bewahrt, stundenlang vor meinem PC zu sitzen und nach einem dummen Fehler zu suchen :) – alex

+1

@alex: Nimm die While-Schleife raus - sie sollte nicht da sein.Idealerweise sollten Sie separate Threads verwenden - einen von 'StandardOutput' und einen von' StandardError'. –

6

Sie haben die Umleitung von Standard Out deaktiviert. Versuchen Sie,

cproc.StartInfo.RedirectStandardOutput = false; 

in

cproc.StartInfo.RedirectStandardOutput = true; 

Hat das folgende Beispiel aus MSDN Arbeit für Sie?

// 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(); 
+0

noch nichts ändert – alex

+0

auch das macht das Fenster erscheinen, aber das ist leer, und mein Ergebnis-String ist leer, auch. das ist wirklich verwirrend – alex

+0

Haben Sie Standardfehler überprüft: 'output = p.StandardError.ReadToEnd();'? –

-1

Entfernen Sie die Schleife und verschieben Sie den Anruf zu ReadToEnd zu cproc_Exited.

+0

Schlechte Idee: Der Prozess wird hängen bleiben, wenn er versucht, viele Daten zu schreiben, die nichts lesen. –

15

Der beste Weg dafür ist die Ausgabe und wartet auf die Ereignisse umleiten:

// some of the flags are not needed 
    process.StartInfo.CreateNoWindow = true; 
    process.StartInfo.ErrorDialog = false; 
    process.StartInfo.UseShellExecute = false; 
    process.StartInfo.RedirectStandardError = true; 
    process.StartInfo.RedirectStandardInput = true; 
    process.StartInfo.RedirectStandardOutput = true; 
    process.EnableRaisingEvents = true; 
    process.OutputDataReceived += process_OutputDataReceived; 
    process.ErrorDataReceived += process_OutputDataReceived; 
    process.Exited += process_Exited; 
    process.Start(); 
    process.BeginErrorReadLine(); 
    process.BeginOutputReadLine(); 

    void process_Exited(object sender, System.EventArgs e) 
    { 
     // do something when process terminates; 
    } 

    void process_OutputDataReceived(object sender, DataReceivedEventArgs e) 
    { 
     // a line is writen to the out stream. you can use it like: 
     string s = e.Data; 
    } 

    void process_ErrorDataReceived(object sender, DataReceivedEventArgs e) 
    { 
     // a line is writen to the out stream. you can use it like: 
     string s = e.Data; 
    } 
+0

Nützlich. Vielen Dank. –