.net - How to read from Process.StandardOutput without redirecting it? (F#) -
i've got little function saves me headaches dealing horrible 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())
this works great, because tuple of 3 elements exitcode, stdout , stderr results.
now, suppose don't want "hide" execution. is, want write hypothetical, simpler, exec function. solution not redirect stdout/stderr , we're done:
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
however, nice if refactor 2 functions converge them single one, , pass "hidden" bool flag it:
let newexec (command: string, arguments: string, hidden: bool) =
this way, newexec(_,_,false)
return stdout,stderr (not exitcode, before). problem if don't redirection dance (startinfo.redirectstandarderror <- true
) cannot read output later via proc.standardoutput.readtoend()
because error standardout has not been redirected or process hasn't started yet
.
another option redirect outputs, , if hidden flag passed not true, call console.writeline(eachoutput)
, not elegant because write buffers in 1 go, without intercalating stderr between stdout lines in screen in proper order come. , long running processes, hide incremental output until process has finished.
so what's alternative here? need resort using damned events process
class? :(
cheers
i follow "parameterize things" principle.
in case, means finding differences between hiddenexec
, exec
, parameterizing these differences functions.
here's end when that:
let execwith configurestartinfo returnfromproc (command: string, arguments: string) = let startinfo = new system.diagnostics.processstartinfo(command) startinfo.arguments <- arguments startinfo.useshellexecute <- false // parameterize bit configurestartinfo startinfo use proc = system.diagnostics.process.start(startinfo) proc.waitforexit() // parameterize bit returnfromproc proc
note passing in various returnfromproc
functions, can change type of return value, want.
now can define hiddenexec
specify redirect , 3-tuple return value did originally:
/// specialize execwith redirect output. /// return exit code , output , 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 -- command & arguments passed later execwith configurestartinfo returnfromproc
the signature shows have want: pass command & arguments tuple , 3-tuple in return:
val hiddenexec : string * string -> int * string * string
note i'm using partial application here. have defined hiddenexec
explicit parameters this:
let hiddenexec (command, arguments) = // (command, arguments) passed here let configurestartinfo ... let returnfromproc ... execwith configurestartinfo returnfromproc (command, arguments) // (command, arguments) passed here
similarly can define exec
not use redirect, this:
/// specialize execwith not redirect output. /// return exit code. /// signature: string * string -> int let exec = let configurestartinfo _ = () // ignore input let returnfromproc (proc:system.diagnostics.process) = proc.exitcode execwith configurestartinfo returnfromproc // alternative version using `ignore` , lambda // execwith ignore (fun proc -> proc.exitcode)
again, signature shows have simpler version wanted: pass command & arguments tuple , exitcode in return:
val exec : string * string -> int
Comments
Post a Comment