重定向.Net中的stdin和stdout

时间:2009-11-24 06:42:55

标签: c# .net f#

我正在尝试重定向控制台应用程序的stdin和stdout,以便我可以通过F#与它们进行交互。但是,根据控制台应用程序,明显的代码似乎失败了。以下F#代码适用于dir,但pythonfsi失败(挂起):

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()

这对于python来说很有用,但是对于dir很有用。

这是否与使用readline的python和fsi有关,还是我犯了一个明显的错误?有没有可以让我与F#的fsi或python REPL进行交互?

3 个答案:

答案 0 :(得分:3)

这是您正在寻找的代码(我在第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> ")

答案 1 :(得分:2)

我敢打赌,python和fsi实际上生成要读取的文本行。对ReadLine的调用将被阻止,直到以回车符或换行符结尾的整行为止。

尝试一次阅读一个角色(Read代替ReadLine),看看会发生什么。

答案 2 :(得分:2)

这可能是Michael Petrotta所说的。如果是这样的话,即使阅读一个角色也无济于事。您需要做的是使用异步版本(BeginOutputReadLine),以便您的应用不会阻止。