Frage

Ich betrachte versuchen, einen Prozess von F # zu starten, warten, bis es fertig ist, sondern auch zunehmend sein Ausgang lesen.

Ist das der richtige / beste Weg, es zu tun? (In meinem Fall ich versuche git Befehle auszuführen, aber das ist tangential zur Frage)

let gitexecute (logger:string->unit) cmd = 
    let procStartInfo = new ProcessStartInfo(@"C:\Program Files\Git\bin\git.exe", cmd) 

    // Redirect to the Process.StandardOutput StreamReader.
    procStartInfo.RedirectStandardOutput <- true
    procStartInfo.UseShellExecute <- false;

    // Do not create the black window.
    procStartInfo.CreateNoWindow <- true;

    // Create a process, assign its ProcessStartInfo and start it
    let proc = new Process();
    proc.StartInfo <- procStartInfo;
    proc.Start() |> ignore

    // Get the output into a string
    while not proc.StandardOutput.EndOfStream do
        proc.StandardOutput.ReadLine() |> logger

Was ich nicht verstehe, ist, wie die proc.Start () eine boolean zurückgeben kann und auch asynchron genug für mich sein, um die Ausgabe zu erhalten, aus dem während progressiv.

Leider habe ich momentan keine ausreichend große Repository haben - oder langsam genug Maschine, in der Lage sein zu sagen, was um Dinge geschehen in ...

UPDATE

Ich habe versucht, Brian Vorschlag, und es funktioniert.

Meine Frage war ein bisschen vage. Mein Missverständnis war, dass ich davon aus, dass Process.Start (), um den Erfolg des Prozesses als Ganzes zurückkehrte, und nicht nur der ‚Start‘, und so konnte ich nicht sehen, wie es könnte Arbeit.

War es hilfreich?

Lösung

Der Code, den Sie in der Form geschrieben Sie schrieb es ist (fast) ok: Process.Start den Prozess starten Sie angeben, in, na ja, ein anderer Prozess, so dass Ihr Ausgangsstrom mit der Prozessausführung parallel passiert, liest. Ein Problem ist aber, dass Sie in einem Aufruf an process.WaitForExit am Ende werfen sollen -. Die Tatsache, dass Ausgangsstrom geschlossen ist, bedeutet nicht, dass Prozess beendet

Jedoch Sie Probleme mit synchronyous Lesung laufen wird, wenn Sie versuchen, Fehler- und Standardausgaben des Prozesses zu lesen: Es gibt keine Möglichkeit, 2-Streams synchron zu lesen und gleichzeitig - Sie werden Deadlocks, wenn Sie stdout lesen und verarbeiten zu stderr schreibt und wartet, bis Sie seinen Ausgang oder umgekehrt zu konsumieren.

Um dies zu vermitteln, die Sie OutputDataRecieved und ErrorDataRecieved abonnieren können, wie folgt aus:

type ProcessResult = { exitCode : int; stdout : string; stderr : string }

let executeProcess (exe,cmdline) =
    let psi = new System.Diagnostics.ProcessStartInfo(exe,cmdline) 
    psi.UseShellExecute <- false
    psi.RedirectStandardOutput <- true
    psi.RedirectStandardError <- true
    psi.CreateNoWindow <- true        
    let p = System.Diagnostics.Process.Start(psi) 
    let output = new System.Text.StringBuilder()
    let error = new System.Text.StringBuilder()
    p.OutputDataReceived.Add(fun args -> output.Append(args.Data) |> ignore)
    p.ErrorDataReceived.Add(fun args -> error.Append(args.Data) |> ignore)
    p.BeginErrorReadLine()
    p.BeginOutputReadLine()
    p.WaitForExit()
    { exitCode = p.ExitCode; stdout = output.ToString(); stderr = error.ToString() }

Sie können auch Schreib etwas entlang der Linien von:

async {
    while true do
        let! args = Async.AwaitEvent p.OutputDataReceived
        ...
} |> Async.StartImmediate

für F # -Stil reaktive Ereignisbehandlung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top