使用.NET的Process类重定向标准输入/输出/错误流

时间:2011-08-15 21:37:06

标签: c# process stdout stdin stderr

我正在尝试为基于交互式控制台的应用程序编写包装器。为此,我使用C#和Process类。我正在尝试重定向stdin / out / err,但它不起作用。

示例代码:

ProcessStartInfo startInfo = new ProcessStartInfo("admin.exe");
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardInput = true;
startInfo.UseShellExecute = false;

Process process = Process.Start(startInfo);
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
process.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data);

while (true)
{
    process.StandardInput.Write("uptime" + Environment.NewLine);
    process.StandardInput.Flush();
    Thread.Sleep(1000);
}
Console.ReadKey();

什么都没发生。但如果我开始admin.exe并写uptime,则会打印输出。

互联网上的所有解决方案都使用ReadToEnd,但我无法使用此功能,因为我有动态通信,我必须阅读stdout / err并写入{{ 1}}。

有人有想法吗?

更新

我在链接线程上使用发布的zip进行了播放。然后我尝试创建一个小的“概念验证”代码:

stdin

完美无缺: - )

但是使用using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.IO; using System.Threading; namespace ConsoleApplication3 { class Program { private static void Read(StreamReader reader) { new Thread(() => { while (true) { int current; while ((current = reader.Read()) >= 0) Console.Write((char)current); } }).Start(); } static void Main(string[] args) { ProcessStartInfo startInfo = new ProcessStartInfo(@"cmd.exe"); startInfo.CreateNoWindow = true; startInfo.ErrorDialog = false; startInfo.RedirectStandardError = true; startInfo.RedirectStandardInput = true; startInfo.RedirectStandardOutput = true; startInfo.UseShellExecute = false; startInfo.CreateNoWindow = true; Process process = new Process(); process.StartInfo = startInfo; process.Start(); Read(process.StandardOutput); Read(process.StandardError); while (true) process.StandardInput.WriteLine(Console.ReadLine()); } } } 它不起作用? admin.exe不使用任何棘手的输入法,也不需要输入密码。

我知道admin.exe是用c编写的,并在linux上用mingw编译。所以我创建了一个小型虚拟工具:

admin.exe

此工具仅回显输入的文本/行。我用#include <stdio.h> int main() { int readed; while ((readed = fgetc(stdin)) >= 0) fputc((char)readed, stdout); } 编译它并将其复制到我的Windows机器上。在那里,我使用这篇文章顶部的程序与i586-mingw32msvc-gcc进行通信。它不起作用。没有显示回声。但为什么呢?

我也使用Microsoft C ++编译器编译了虚拟代码,效果相同。

UPDATE2

<顺便说一句(顺便说一下:感谢Tim Post)

我正在努力尝试。我尝试创建一个c-Tool,它和我的c#工具一样。我使用dummy.exe,但效果是,输出显示在流程结束时。嗯,不好。

我为windows找到了这个替代命令shell:

https://stackoverflow.com/questions/440269/whats-a-good-alternative-windows-console

http://sourceforge.net/projects/console/

似乎有效。它实时获取stdout / err,可以重定向标准输入和_popen工作。它是开源的。也许我会在C ++ - Code中找到解决方案。

我在C ++方面表现不佳,所以很难,但我会尝试一下。可能我必须用C / C ++编写一个“清晰”的重定向包装器并在C#中使用它。

如果有人有想法请说出来,因为另一种方式可能非常难(对我来说^^): - )

感谢。

最好的问候

更新3

嗯,我认为这是因为子进程(admin.exe)使用了几个线程... 但是如何解决呢?

1 个答案:

答案 0 :(得分:1)

问题可能是,因为你正在使用Readline,其中数据是从admin.exe应用程序输出的,是顺序而不是新行...,尝试使用相反,Read,并从中构建所需的字符串..

此外,您不必使用Environment.NewLine来编写字符串后跟新行,而是使用WriteLine,所以:

process.StandardInput.WriteLine("uptime");