C# 在.Net中重定向stdin和stdout
我试图重定向控制台应用程序的stdin和stdout,以便通过F#与它们交互。但是,根据控制台应用程序的不同,明显的代码似乎会失败。以下F#代码适用于C# 在.Net中重定向stdin和stdout,c#,.net,f#,C#,.net,F#,我试图重定向控制台应用程序的stdin和stdout,以便通过F#与它们交互。但是,根据控制台应用程序的不同,明显的代码似乎会失败。以下F#代码适用于dir,但在python和fsi中失败(挂起): open System open System.Diagnostics let f = new Process() f.StartInfo.FileName <- "python" f.StartInfo.UseShellExecute <- false f.StartInfo.Red
dir
,但在python
和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()
开放系统
开放系统诊断
设f=新进程()
f、 StartInfo.FileName我敢打赌python和fsi实际上都没有生成一行要读取的文本。对ReadLine
的调用将被阻止,直到以回车符或换行符结尾的整行可用为止
试着一次读一个字符(用Read
而不是ReadLine
),看看会发生什么。迈克尔·彼得罗塔可能是这么说的。如果是这样的话,即使是读一个角色也没有帮助。您需要做的是使用异步版本(),这样您的应用程序就不会被阻塞。这就是您正在寻找的代码(我在第9章脚本中很方便地写了这段代码),如前所述,ReadLine会被阻塞,直到出现导致各种挂起的完整行。最好的方法是挂接OutputDataReceived事件
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())
这是完美的,除了我还在努力弄清楚如何找到每个命令输出的起点和终点之外。在>上拆分似乎不太可靠。我尝试将“-fsi server:test”作为参数传递,但似乎没有得到“server-PROMPT>”。有什么想法吗?不幸的是,在FSI中,除了等待“>”显示之外,没有办法知道是否执行了命令,这显然不是很可靠。(在生成比任务执行时间更长的异步任务时,这会变得更加棘手。)对于自动化,我们使用以下启发式方法:等待“\r\n>”&&一秒钟或更长时间没有写入新的输出。谢谢。fsiserver.fs似乎在IPC上工作,但如何像VS外壳一样使用它并不明显。
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> ")