gpt4 book ai didi

.net - 如何在不重定向的情况下读取 Process.StandardOutput ? (F#)

转载 作者:行者123 更新时间:2023-12-02 16:46:11 28 4
gpt4 key购买 nike

我有这个小函数,可以让我在处理可怕的 System.Diagnostics.Process API 时省去一些麻烦:

let HiddenExec (command: string, arguments: string) =
let startInfo = new System.Diagnostics.ProcessStartInfo(command)
startInfo.Arguments <- arguments
startInfo.UseShellExecute <- false

startInfo.RedirectStandardError <- true
startInfo.RedirectStandardOutput <- true

use proc = System.Diagnostics.Process.Start(startInfo)
proc.WaitForExit()
(proc.ExitCode,proc.StandardOutput.ReadToEnd(),proc.StandardError.ReadToEnd())

这非常有效,因为我得到了包含退出代码、stdout 和 stderr 结果的三个元素的元组。

现在,假设我不想“隐藏”执行。也就是说,我想编写一个假设的、更简单的 Exec 函数。那么解决方案是不重定向 stdout/stderr,我们就完成了:

let Exec (command: string, arguments: string) =
let startInfo = new System.Diagnostics.ProcessStartInfo(command)
startInfo.Arguments <- arguments
startInfo.UseShellExecute <- false

let proc = System.Diagnostics.Process.Start(startInfo)
proc.WaitForExit()
proc.ExitCode

但是,如果我可以重构这两个函数以将它们聚合为一个函数,然后向其传递一个“隐藏” bool 标志,那就太好了:

let NewExec (command: string, arguments: string, hidden: bool) =

这边,NewExec(_,_,false)还将返回 stdout、stderr(不仅像以前一样返回 exitCode)。问题是,如果我不进行重定向舞蹈( startInfo.RedirectStandardError <- true ),那么我无法稍后通过 proc.StandardOutput.ReadToEnd() 读取输出。因为我收到错误 StandardOut has not been redirected or the process hasn't started yet .

始终重定向输出的另一个选项,如果传递的隐藏标志不为 true,则调用 Console.WriteLine(eachOutput) ,但这不是很优雅,因为它会一次性写入缓冲区,而不会按照它们出现的正确顺序在屏幕中的 stdout 行之间插入 stderr。对于长时间运行的进程,它将隐藏增量输出,直到进程完成。

那么这里有什么选择呢?我是否需要诉诸使用 Process 中的该死的事件?类(class)? :(

干杯

最佳答案

我会遵循“参数化所有事物”的原则。

在这种情况下,这意味着找到 HiddenExecExec 之间的差异,然后用函数参数化这些差异。

这就是我这样做时的结果:

let ExecWith configureStartInfo returnFromProc (command: string, arguments: string) =
let startInfo = new System.Diagnostics.ProcessStartInfo(command)
startInfo.Arguments <- arguments
startInfo.UseShellExecute <- false

// parameterize this bit
configureStartInfo startInfo

use proc = System.Diagnostics.Process.Start(startInfo)
proc.WaitForExit()

// parameterize this bit too
returnFromProc proc

请注意,通过传入各种 returnFromProc 函数,您可以根据需要更改返回值的类型。

现在您可以定义 HiddenExec 来指定重定向和三元组返回值,就像您最初所做的那样:

/// Specialize ExecWith to redirect the output.
/// Return the exit code and the output and error.
/// Signature: string * string -> int * string * string
let HiddenExec =

let configureStartInfo (startInfo: System.Diagnostics.ProcessStartInfo) =
startInfo.RedirectStandardError <- true
startInfo.RedirectStandardOutput <- true

let returnFromProc (proc:System.Diagnostics.Process) =
(proc.ExitCode,proc.StandardOutput.ReadToEnd(),proc.StandardError.ReadToEnd())

// partial application -- the command & arguments are passed later
ExecWith configureStartInfo returnFromProc

签名表明我们已经得到了我们想要的:您传递一个命令和参数元组并获得 3 元组作为返回:

val HiddenExec : string * string -> int * string * string

请注意,我在这里使用部分应用程序。我还可以使用如下显式参数定义 HiddenExec:

let HiddenExec (command, arguments) =  // (command, arguments) passed here

let configureStartInfo ...
let returnFromProc ...

ExecWith configureStartInfo returnFromProc (command, arguments) // (command, arguments) passed here

同样,您可以将 Exec 定义为使用重定向,如下所示:

/// Specialize ExecWith to not redirect the output.
/// Return the exit code.
/// Signature: string * string -> int
let Exec =

let configureStartInfo _ =
() // ignore the input

let returnFromProc (proc:System.Diagnostics.Process) =
proc.ExitCode

ExecWith configureStartInfo returnFromProc

// alternative version using `ignore` and lambda
// ExecWith ignore (fun proc -> proc.ExitCode)

签名再次表明我们拥有我们想要的更简单的版本:您传递命令和参数元组并仅获取 ExitCode 作为返回:

val Exec : string * string -> int 

关于.net - 如何在不重定向的情况下读取 Process.StandardOutput ? (F#),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38459064/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com