【问题标题】:Determining end of console output确定控制台输出的结束
【发布时间】:2015-07-13 17:47:21
【问题描述】:

我在我的应用程序中收到控制台输出。我使用来自here 的代码(公认的解决方案)。 但我从来没有在我的 OutputDataReceived 中得到 null。相反,我在输出的末尾有 String.Empty。 使用 String.NullOrEmpty 而不是仅与 null 进行比较是否正确?

static void Main(string[] args)
        {
            var command = @"wmic cpu get loadpercentage";
            using (Process process = new Process())
            {
                process.StartInfo.FileName = "cmd.exe";
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.CreateNoWindow = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardInput = true;
                process.StartInfo.RedirectStandardError = true;

                StringBuilder output = new StringBuilder();
                StringBuilder error = new StringBuilder();

                using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
                using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
                {
                    process.OutputDataReceived += (sndr, a) =>
                    {
                        if (a.Data == null)
                        {
                            outputWaitHandle.Set();
                        }
                        else
                        {
                            output.AppendLine(a.Data);
                        }
                    };
                    process.ErrorDataReceived += (sndr, a) =>
                    {
                        if (a.Data == null)
                        {
                            errorWaitHandle.Set();
                        }
                        else
                        {
                            error.AppendLine(a.Data);
                        }
                    };

                    process.Start();
                    process.BeginOutputReadLine();    
                    outputWaitHandle.WaitOne();

                    string path = "Test.txt";
                    using (StreamWriter sw = File.Exists(path) ? File.AppendText(path) : File.CreateText(path))
                    {
                        sw.WriteLine(String.Format("{0}, {1}", DateTime.Now, output));

                    }

                }
            }
        }

更新: 多行输出好像不行。问题是为什么 a.Data 中没有 null

【问题讨论】:

  • 你应该总是在最后得到一个null。您没有收到它的原因是您没有等待进程终止。您需要在 process.Start() 之后的某个位置使用 process.WaitForExit()(特别是在进程在调用 BeginOutputReadLine 之前退出的情况下)。
  • @Cameron 但我的进程 (cmd.exe) 永远不会退出。我想使用 process.StandardInput.WriteLine 键入多个命令并接收相应的输出
  • 您发布的代码设置后没有使用命令变量,您的新进程可能什么都不做
  • 如果进程永远不会退出,那么它的标准输出将保持打开状态(默认情况下,无论如何),您将永远不会收到 null。您究竟想通过这些自动重置事件来完成什么?
  • @amplifier 否是问题的答案 - 正如 Cameron 指出的那样,CMD 不会在您的代码中停止(而且看起来正是您想要实现某种远程 CMD / telnet) - 所以它永远不会有“输出结束”。此外,没有任何类型的“命令执行结束”标记,因此您真的看不到“ping”或任何其他命令是否完成或等待用户输入或打开自己的子提示,如“ftp”。跨度>

标签: c# processstartinfo


【解决方案1】:

标准输出流仅随着进程本身的终止而终止。请注意,这里的“进程”表示运行cmd.exe 的进程。该进程可以启动其他进程,但它们有自己的标准输出流,虽然这些进程的标准输出将在它们自己终止时终止,但这些都不会影响父进程cmd.exe 的标准输出。

如果您想通过模拟用户对cmd.exe 的输入来运行一个运行各种其他进程的进程,那么您还必须模拟能够识别并响应正在执行的最终命令的用户交互。

想象自己身处真实用户的位置,并思考他们如何处理这种情况。当他们在命令提示符窗口中执行命令时,命令完成后该窗口是否关闭?不会。他们是否收到任何指示命令已完成的指示?有点。首先,他们可能期望命令的输出符合某种特定的格式,这通常会包含一些命令已完成的指示符。其次,命令提示符窗口会显示一个新的提示符(即短语“command-prompt”中的“prompt”)。

请注意,恶意命令可能会找出当前提示的外观并伪造它。但这是不寻常的,大概您对发出的命令有足够的控制权来避免这种情况。因此,一种方法是在输出发生时简单地对其进行处理,并检测命令完成时出现的新提示。

如果这看起来不够可靠,那么您将不得不单独处理每个命令,解释命令的输出,并仅从该输出中的内容识别该命令何时到达其输出的末尾。

最后请注意,您实际上可以使用Process 类自己执行命令。你不需要cmd.exe 来做到这一点。如果您自己将每个命令作为一个单独的进程执行,那么您确实最终会通过每个进程的标准输出的流结束收到进程终止的通知。

【讨论】:

  • “任何表明命令已完成的指示”,是的,这就是我正在考虑的。谢谢!
猜你喜欢
  • 2014-02-24
  • 2020-10-11
  • 1970-01-01
  • 2014-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-10
相关资源
最近更新 更多