【问题标题】:How to interact with a process through stdout and stdin如何通过 stdout 和 stdin 与进程交互
【发布时间】:2015-12-27 22:12:42
【问题描述】:

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

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,但它们也不起作用。

我该如何解决这个问题?

【问题讨论】:

  • 从内存中旧版本(可能还有新版本)使用奇怪的事件循环来读取可能绕过标准输入的输入。你到底想在这里做什么?
  • @JohnPalmer 在此代码中,我试图一遍又一遍地发送一行代码。我最终试图做出一种概括的repl。
  • @JohnPalmer 不完全是。我所说的广义 repl 的意思是这个程序可以用作 python 或 ruby​​(或其他任何东西)repl 接口。它基本上是多个后端的前端。您提到的项目甚至建议在某些情况下使用标准输入和标准输出 - fsharp.github.io/FSharp.Compiler.Service/interactive.html

标签: .net windows process f#


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2021-03-20
    • 2017-08-18
    • 2014-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-22
    • 2012-05-20
    • 2011-05-05
    相关资源
    最近更新 更多