Reputation: 1446
I'm trying start an F# interactive subprocess, send code to it through standard input, and receive the response through standard output. Here is the code of my attempt (the command line args are just fsi
, which is on the path"):
let readStrStream (stream : StreamReader) =
let buffer = Array.create 1024 (char 0)
let bytesReceived = stream.Read(buffer, 0, 1024)
let chars = buffer |> Array.take bytesReceived
let str = String.Concat(chars)
str
let rec loop (proc : Process) = async {
proc.StandardInput.WriteLine("printf \"iteration\"")
let output = readStrStream proc.StandardOutput
printfn "%s" output
let error = readStrStream proc.StandardError
printfn "%s" error
return! loop proc }
let start proc =
Async.Start(loop proc, cancellationToken = cts.Token)
{ new IDisposable with member x.Dispose() = cts.Cancel }
[<EntryPoint>]
let main argv =
let procStart = new ProcessStartInfo(argv.[0], argv.[1..] |> String.concat " ")
procStart.UseShellExecute <- false
procStart.RedirectStandardInput <- true
procStart.RedirectStandardOutput <- true
procStart.RedirectStandardError <- true
procStart.WorkingDirectory <- "C:\\Users\\Philip"
let proc = Process.Start(procStart)
proc.StandardInput.AutoFlush <- true
let x = start proc
let y = Console.ReadLine()
0
This code does not work. When I run it, it just prints 2 newlines.
If I change the code like so,
let proc = Process.Start(procStart)
Thread.Sleep(10000)
The program prints out
Microsoft (R) F# Interactive version 14.0.23020.0
Copyright (c) Microsoft Corporation. All Rights Reserved.
For help type #help;;
>
Which is the startup text of fsi
.
I did some debugging, and here is what I found.
In the first code, both calls to readStrStream
return \r\n
on the first iteration, and on the second iteration, they first call hangs.
In the second code, the call returns the fsi
output.
It seems to me that for some reason the stream is closing down after one call to stream.Read
.
I've been playing with other things besides fsi, like python or irb, but they did not work either.
How do I fix this?
Upvotes: 0
Views: 671
Reputation: 1446
I figured out how to fix it, but I don't entirely understand all that is going on. This answer helped me find the solution. Redirecting stdin and stdout in .Net.
The trick is to use proc.BeginOutputReadLine()
and then subscribe to proc.OutputDataReceived
instead of calling readline. I think the reason this works has something to do with it being asynchronous.
Upvotes: 1