2015-12-27 44 views
0

我试图启动一个F#交互子程序,通过标准输入向它发送代码,并通过标准输出接收响应。这是我尝试(在命令行参数只是fsi,这是道路上“)的代码:。如何通过stdout和标准输入与进程进行交互

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 

此代码不能正常工作当我运行它,它只是打印2个换行符

如果我改变,像这样的代码,

let proc = Process.Start(procStart) 
Thread.Sleep(10000) 

程序打印出

Microsoft (R) F# Interactive version 14.0.23020.0 
Copyright (c) Microsoft Corporation. All Rights Reserved. 

For help type #help;; 

> 

这是fsi的启动文本。

我做了一些调试,这里是我发现的。 在第一个代码中,在第一次迭代中,两个对readStrStream的调用返回\r\n,在第二次迭代中,他们首先调用挂起。

在第二个代码中,该调用返回fsi输出。

在我看来,由于某种原因,一个电话打到stream.Read后,流正在关闭。

我一直在玩fsi以外的其他东西,比如python或者irb,但是它们也没有工作。

我该如何解决这个问题?

+0

来自内存旧版本(可能还有新版本)使用奇怪的事件循环来读取可能绕过标准输入的输入。无论如何,你想在这里做什么? –

+0

@JohnPalmer在这里的代码,我试图一遍又一遍地发送一行代码。我最终想做一个广义的repl。 – phil

+0

我想你想要https://github.com/fsharp/FSharp.Compiler.Service –

回答

1

我想出了如何解决这个问题,但我并不完全理解所发生的一切。 这个答案帮助我找到解决方案。 Redirecting stdin and stdout in .Net

诀窍是使用proc.BeginOutputReadLine(),然后订阅proc.OutputDataReceived而不是调用readline。我认为这起作用的原因与它异步有关。

相关问题