【发布时间】:2011-10-27 14:51:34
【问题描述】:
我正在尝试为基于控制台的交互式应用程序编写包装器。为此,我使用 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并写信给stdin。
有人有想法吗?
更新
我玩过链接线程上发布的 zip。然后我尝试创建一个小的“概念验证”代码:
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 不使用任何棘手的输入法,也不需要输入密码。
我知道admin.exe 是用c 编写的,并在Linux 上用mingw 编译。所以我创建了一个小虚拟工具:
#include <stdio.h>
int main() {
int readed;
while ((readed = fgetc(stdin)) >= 0)
fputc((char)readed, stdout);
}
此工具仅回显输入的文本/行。我用i586-mingw32msvc-gcc 编译它并将它复制到我的Windows 机器上。在那里,我使用了这篇文章顶部的程序与dummy.exe 进行通信。它不起作用。没有显示回声。但为什么呢?
我也用 Microsoft C++ Compiler 编译了虚拟代码,效果相同。
更新2
(顺便说一句:感谢 Tim Post)
我一直在尝试。我试图创建一个 c-Tool,它和我的 c# 工具一样。我使用了_popen,但效果是,输出显示在进程结束时。嗯,不好。
我找到了这个 Windows 的替代命令外壳:
https://stackoverflow.com/questions/440269/whats-a-good-alternative-windows-console
http://sourceforge.net/projects/console/
它似乎工作。它实时获取标准输出/错误,可以重定向标准输入和admin.exe 工作。它是开源的。也许我会在 C++ 代码中找到解决方案。
我的 C++ 不好,所以很难,但我会试试的。可能我必须在 C/C++ 中编写一个“清晰”的重定向包装器并在 C# 中使用它。
如果有人有想法请说出来,因为另一种方式可能很难(对我来说^^):-)
谢谢。
最好的问候
更新 3
嗯,我认为这是因为子进程 (admin.exe) 使用了几个线程...
但是如何解决呢?
【问题讨论】:
-
我遇到了完全相同的问题,并提出了一个(有点笨拙的)解决方案,您可以在这里找到:stackoverflow.com/questions/6655613/…。我相信这也有一个指向 .ZIP 的链接以及完整的解决方案。
-
有些程序只是对输入/输出重定向很感兴趣。 Admin.exe 是一个强大的提示,它会想要从真正的控制台读取密码。
-
我已合并您未注册的帐户并将您的答案转换为对您问题的编辑,请检查准确性。您现在应该可以完全控制自己的问题和答案了。
-
您可能对this post 感兴趣,它涵盖了使用 .NET 进程的许多复杂性,尤其是在处理输入和输出方面。它推荐MedallionShell库,它简化了处理进程io流
-
如果一次读取一个字符会怎样? ReadLine 需要按回车键。 while (true) { p.StandardInput.Write(Console.ReadKey()); }
标签: c# process stdout stdin stderr