我在应用程序中收到控制台输出。我使用来自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
中没有空答案 0 :(得分:2)
标准输出流仅在进程本身终止时终止。注意,在这里,"过程"表示正在运行的进程cmd.exe
。该进程可以启动其他进程,但是它们有自己的标准输出流,而这些进程的stdout将在它们自己终止时终止,但这些都不会影响父进程{{1}过程' s stdout。
如果您希望通过模拟cmd.exe
的用户输入来运行运行各种其他进程的进程,那么您还必须模拟可识别并响应正在执行的最终命令的用户交互。
想象一下自己在一个真实的用户中,并思考他们如何应对这种情况。当他们在命令提示符窗口中执行命令时,该命令完成时该窗口是否关闭?不。他们是否收到命令已完成的任何指示?有点。首先,他们可能希望命令的输出符合某种特定格式,这通常包括命令已完成的一些指示。其次,命令提示符窗口将显示一个新提示(即"提示"在短语"命令提示符")。
请注意,恶意命令可以找出当前提示的内容并伪造它。但这很不寻常,大概是你对你发出的命令有足够的控制权来避免这种情况。因此,一种方法是简单地处理输出,并检测命令完成时出现的新提示。
如果这看起来不够可靠,那么您将不得不单独处理每个命令,解释命令的输出并识别该命令何时仅从该输出中的内容到达其输出的结尾。
最后请注意,您实际上可以使用cmd.exe
类来自行执行命令。你不需要Process
来做到这一点。如果您自己将每个命令作为一个单独的进程执行,那么您做最终会通过每个进程的stdout流结束获得进程终止的通知。