Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在.Net中重定向stdin和stdout_C#_.net_F# - Fatal编程技术网

C# 在.Net中重定向stdin和stdout

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

我试图重定向控制台应用程序的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.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> ")