【问题标题】:Console input redirect控制台输入重定向
【发布时间】:2012-02-29 21:06:05
【问题描述】:

我正在编写一个 Windows 应用程序,它通过将 cmd.exe 的输入和输出重定向到文本框来模拟控制台。起始代码如下:

StreamWriter inputWriter;
StreamReader outputReader;
StreamReader errorReader;
Process proc = new Process();
byte[] outputBuffer = new byte[1024];
byte[] errorBuffer = new byte[1024];

proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.Arguments = "/Q";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.ErrorDialog = false;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardInput = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
inputWriter = proc.StandardInput;
outputReader = proc.StandardOutput;
errorReader = proc.StandardError;
outputReader.BaseStream.BeginRead(outputBuffer, 0, outputBuffer.Length, ShowOutput, null);
errorReader.BaseStream.BeginRead(errorBuffer, 0, errorBuffer.Length, ShowError, null);proc.StartInfo.Arguments = "/Q";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.ErrorDialog = false;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardInput = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
inputWriter = proc.StandardInput;
outputReader = proc.StandardOutput;
errorReader = proc.StandardError;
outputReader.BaseStream.BeginRead(outputBuffer, 0, outputBuffer.Length, ShowOutput, null);
errorReader.BaseStream.BeginRead(errorBuffer, 0, errorBuffer.Length, ShowError, null);

当我启动进程时,我可以读取控制台输出,还可以通过写入输入流向它发送命令。

当我以这种方式启动某个应用程序时,该应用程序的输出也被重定向并且一切正常,但该应用程序似乎没有接收到正在写入输入流的数据。甚至一些控制台命令也无法接收输入。 例如如果我打电话给inputWriter.WriteLine("del *.log");,我会收到“你确定”提示,但是当我打电话给inputWriter.Write("y"); 时,控制台会回显“y”但没有任何反应,控制台会继续等待输入。 如果我调用 inputWriter.WriteLine("pause"); 控制台暂停并在 inputWriter.Write(" "); 之后继续正常运行。

这里有什么问题,我怎样才能正确地将输入重定向到控制台和正在其中执行的应用程序(和命令)?

提前致谢。

干杯!

【问题讨论】:

    标签: c# .net process console


    【解决方案1】:

    这是一个有趣的问题,它可能与 win32 命令解释器出于安全原因处理输入的方式有关。有几个项目(大部分)已经解决了这些问题,例如this one。您可能需要查看代码(虽然它是 C++),以尝试找出是否需要实施一些技巧来绕过输入限制(如果确实应该归咎于它们)。

    我认为我从未见过用 C# 编写的完整控制台替换解决方案。

    【讨论】:

    • 我见过的最接近控制台替换的想法是 POSH 控制台。是的,我不知道细节,但是控制台编程很笨拙,甚至 Powershell 也有一些限制,因为 Windows 控制台的工作方式。
    【解决方案2】:

    我已经多次这样做了。问题是因为您的程序是单线程的。您需要运行进程 asyc。这是我的一个例子。

     private void exportButton_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process p = new System.Diagnostics.Process();
    
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.Arguments = "";
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.CreateNoWindow = true;
    
            p.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(ConsoleOutputHandler);
    
            p.Start();
            p.BeginOutputReadLine();
    
            //p.WaitForExit();
            //p.Dispose();
        }
    
        private void UpdateTextBox(String message)
        {
            if (consoleOutputBox.InvokeRequired)
            {
                UpdateConsoleWindowDelegate update = new UpdateConsoleWindowDelegate(UpdateTextBox);
                consoleOutputBox.BeginInvoke(update, message);
            }
            else
            {
                consoleOutputBox.AppendText(message);
            }
        }
    
        void ConsoleOutputHandler(object sendingProcess, System.Diagnostics.DataReceivedEventArgs recieved)
        {
            if (!String.IsNullOrEmpty(recieved.Data))
            {
                UpdateTextBox(recieved.Data + "\n");
            }
        }
    

    【讨论】:

    • 实际上我在输出流上使用 BeginRead 使 id 异步。当控制台(或控制台中运行的程序)等待输入时,写入输入流会导致问题。我可以运行 dir、cd 等命令,但是一旦需要提示(例如 y/n),控制台就不会响应写入输入流的字符。似乎我必须以某种方式找到一个由控制台执行的进程(如果有的话),然后写入该进程的输入流......
    猜你喜欢
    • 2011-06-10
    • 2013-11-14
    • 1970-01-01
    • 2011-02-22
    • 2015-03-10
    • 2015-09-11
    • 2011-05-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多