如何在F#中重定向标准和错误输出

时间:2019-02-02 13:26:38

标签: f#

我正在尝试重定向F#中的标准和错误输出

let RunProcess (processInfo : ProcessStartInfo) =
    let str = StringBuilder()
    processInfo.UseShellExecute <- false
    processInfo.RedirectStandardOutput <- true
    processInfo.RedirectStandardError <- true
    let p = new Process()
    p.StartInfo <- processInfo
    p.OutputDataReceived.Add(fun x -> str.Append(x.Data + Environment.NewLine) |> ignore)
    p.ErrorDataReceived.Add(fun x -> str.Append(x.Data + Environment.NewLine) |> ignore)
    p.Start() |> ignore
    p.BeginOutputReadLine()
    p.BeginErrorReadLine()
    str.ToString()

当我这样做时,什么也没发生。

但是,当我将processInfo.RedirectStandardOutput设置为false时,会在控制台中显示

2 个答案:

答案 0 :(得分:1)

Process.Start()不等待启动的进程完成执行。 可能需要额外的WaitForExit来执行此操作,否则很有可能在完全没有将StringBuilder ToString写入之前调用StringBuilder ToString。

答案 1 :(得分:1)

这是我使用的:

let inline tee    f v   = f v ; v
let inline  (|>!) v f   = f v ; v

let RunProcess (startInfo : ProcessStartInfo) =
    let bufferOutput                      = new StringBuilder()
    let bufferError                       = new StringBuilder()
    let dataHandler               handler = DataReceivedEventHandler(fun sender args -> try handler args.Data with _ -> ())
    let consume   (sb: StringBuilder)     = sb.ToString() |>! (fun _ -> sb.Clear() |> ignore)
    let append    (sb: StringBuilder) txt = sb.Append(txt + "\n") |> ignore
    let outputHandler                     = append bufferOutput   |> dataHandler
    let errorHandler                      = append bufferError    |> dataHandler
    startInfo.RedirectStandardInput      <- true
    startInfo.RedirectStandardOutput     <- true
    startInfo.RedirectStandardError      <- true
    startInfo.UseShellExecute            <- false
    let proc                              = new Process(
                                                StartInfo           = startInfo
                                              , EnableRaisingEvents = true     )
    outputHandler                        |> proc.OutputDataReceived.AddHandler
    errorHandler                         |> proc.ErrorDataReceived .AddHandler
    let r                                 = proc.Start                 () 
    do                                      proc.BeginOutputReadLine   ()
    do                                      proc.BeginErrorReadLine    ()
    do                                      proc.WaitForExit           ()
    let output                            = (consume bufferOutput).Trim()
    let error                             = (consume bufferError ).Trim()
    ((if proc.HasExited then proc.ExitCode else -99999), output, error)