Redirecting stdin and stdout to .Net

I am trying to redirect stdin and stdout of a console application so that I can interact with them through F #. However, depending on the console application, the obvious code seems to fail. The following F # code works for dir, but does not work (hangs) for pythonand fsi:

open System
open System.Diagnostics

let f = new Process()
f.StartInfo.FileName <- "python"
f.StartInfo.UseShellExecute <- false
f.StartInfo.RedirectStandardError <- true
f.StartInfo.RedirectStandardInput <- true
f.StartInfo.RedirectStandardOutput <- true
f.EnableRaisingEvents <- true
f.StartInfo.CreateNoWindow <- true
f.Start()
let line = f.StandardOutput.ReadLine()

This hangs for python, but works for dir.

Is it due to using python and fsi using readline or am I making an obvious mistake? Is there any work that would allow me to interact with fsi or python REPL from F #?

+5
source share
3 answers

, ( 9, ;) , ReadLine , , . OutputDataRecieved.

open System.Text
open System.Diagnostics

let shellEx program args =

    let startInfo = new ProcessStartInfo()
    startInfo.FileName  <- program
    startInfo.Arguments <- args
    startInfo.UseShellExecute <- false

    startInfo.RedirectStandardOutput <- true
    startInfo.RedirectStandardInput  <- true

    let proc = new Process()
    proc.EnableRaisingEvents <- true

    let driverOutput = new StringBuilder()
    proc.OutputDataReceived.AddHandler(
        DataReceivedEventHandler(
            (fun sender args -> driverOutput.Append(args.Data) |> ignore)
        )
    )

    proc.StartInfo <- startInfo
    proc.Start() |> ignore
    proc.BeginOutputReadLine()

    // Now we can write to the program
    proc.StandardInput.WriteLine("let x = 1;;")
    proc.StandardInput.WriteLine("x + x + x;;")
    proc.StandardInput.WriteLine("#q;;")

    proc.WaitForExit()
    (proc.ExitCode, driverOutput.ToString())

( ):

val it : int * string =
  (0,
   "Microsoft F# Interactive, (c) Microsoft Corporation, All Rights ReservedF# Version 1.9.7.8, compiling for .NET Framework Version v2.0.50727For help type #help;;> val x : int = 1> val it : int = 3> ")
+3

, , fsi . ReadLine , , .

( Read ReadLine) , .

+2

This is probably what Michael Petrotta says. If this is the case, even reading the character will not help. What you need to do is use asynchronous versions ( BeginOutputReadLine ) so that your application does not block.

+2
source

All Articles