确定控制台输出的结束
本文关键字:结束 输出 控制台 | 更新日期: 2023-09-27 18:02:24
我在应用程序中接收控制台输出。我使用这里的代码(公认的解决方案)。但我从来没有得到null在我的OutputDataReceived。取而代之的是String。输出末尾的为空。使用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));
}
}
}
}
Update:似乎它不能工作多行输出。问题是为什么a.Data
标准输出流只有在流程本身终止时才会终止。注意,这里的"进程"是指运行cmd.exe
的进程。该进程可以启动其他进程,但它们有自己的标准输出流,虽然这些进程的标准输出将在它们自己终止时终止,但这些都不会影响父进程cmd.exe
的标准输出。
如果您想通过模拟用户输入cmd.exe
来运行一个运行各种其他进程的进程,那么您还必须模拟识别并响应正在执行的最终命令的用户交互。
想象你自己在一个真正的用户的位置,想想他们如何处理这种情况。当他们在命令提示窗口中执行命令时,该窗口是否在命令完成后关闭?不。他们是否收到命令已完成的任何指示?排序的。首先,他们大概期望命令的输出符合某种特定的格式,这种格式通常会包含一些指示符,表明命令已经完成。其次,命令提示窗口将显示一个新的提示符(即短语"command-prompt"中的"prompt")。
请注意,恶意命令可以找出当前提示符的样子并伪造它。但这是不寻常的,想必您对发出的命令有足够的控制来避免这种情况。因此,一种方法是在输出出现时简单地处理输出,并检测命令完成时出现的新提示符。
如果这看起来不够可靠,那么您将不得不单独处理每个命令,解释命令的输出,并仅从该输出中的内容识别该命令何时到达其输出的末尾。
最后请注意,实际上您可以使用Process
类来执行命令本身。你不需要cmd.exe
来做到这一点。如果您自己将每个命令作为一个单独的进程执行,那么将通过每个进程的标准输出的流结束处获得进程终止的通知。