C#获取cmd输出,如real cmd窗口所示
我有一个C#获取cmd输出,如real cmd窗口所示,c#,cmd,C#,Cmd,我有一个BackgroundWorker线程,它运行cmd进程并向其中写入多个命令。有些命令可能需要一段时间才能完成,因此我想向用户显示进度的cmd输出。 我运行cmd命令的代码如下所示: private void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) { var startInfo = new ProcessStartInfo("cmd.exe") {
BackgroundWorker
线程,它运行cmd进程并向其中写入多个命令。有些命令可能需要一段时间才能完成,因此我想向用户显示进度的cmd输出。
我运行cmd命令的代码如下所示:
private void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
var startInfo = new ProcessStartInfo("cmd.exe")
{
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
CreateNoWindow = true
};
cmd = new Process { StartInfo = startInfo };
cmd.OutputDataReceived += Cmd_OutputDataReceived;
cmd.Start();
cmd.BeginOutputReadLine();
cmd.StandardInput.WriteLine($"cd {baseFolder}\\External Resources\\img files\\uboot");
string[] commands = CmdCommands.GetUbootFlashCommands();
foreach (var command in commands)
cmd.StandardInput.WriteLine(command);
cmd.StandardInput.WriteLine($"cd {baseFolder}\\External Resources\\img files\\android");
commands = CmdCommands.GetKernelFlashCommands();
foreach (var command in commands)
cmd.StandardInput.WriteLine(command);
cmd.StandardInput.WriteLine("exit");
cmd.WaitForExit();
}
private void Cmd_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Invoke(new Action(() =>
{
txtCmd.Text += e.Data + Environment.NewLine;
}));
}
但是cmd输出与常规cmd窗口中显示的实际输出没有任何区别。
以下是我的输出的样子:
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.
C:\>cd C:\img files\uboot
C:\img files\uboot>fastboot flash XXX.bin
C:\img files\uboot>fastboot flash XXX.bin
C:\img files\uboot>cd C:\img files\android
C:\img files\android>fastboot flash kernel
C:\img files\android>fastboot flash system XXX.img
C:\img files\android>fastboot flash userdata XXX.img
C:\img files\android>fastboot flash cache XXX.img
C:\img files\android>exit
下面是当我打开cmd窗口并键入命令时输出的样子:
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.
C:\WINDOWS\system32>cd C:\img files\uboot
C:\img files\uboot>fastboot flash bl2 bl2.bin
target didn't report max-download-size
sending 'bl2' (14 KB)...
OKAY [ 0.006s]
writing 'bl2'...
OKAY [ 0.042s]
finished. total time: 0.052s
C:\img files\uboot>fastboot flash bootloader u-boot.bin
target didn't report max-download-size
sending 'bootloader' (275 KB)...
OKAY [ 0.049s]
writing 'bootloader'...
OKAY [ 0.046s]
finished. total time: 0.098s
C:\img files\uboot>cd C:\img files\android
C:\img files\android>fastboot flash kernel zImage-dtb
target didn't report max-download-size
sending 'kernel' (5099 KB)...
OKAY [ 0.839s]
writing 'kernel'...
OKAY [ 0.145s]
finished. total time: 0.988s
C:\img files\android>fastboot flash system system.img
target didn't report max-download-size
sending 'system' (426874 KB)...
OKAY [ 70.327s]
writing 'system'...
OKAY [ 30.963s]
finished. total time: 101.295s
C:\img files\android>fastboot flash userdata userdata.img
target didn't report max-download-size
sending 'userdata' (35680 KB)...
OKAY [ 5.895s]
writing 'userdata'...
OKAY [ 2.301s]
finished. total time: 8.200s
C:\img files\android>fastboot flash cache cache.img
target didn't report max-download-size
sending 'cache' (6248 KB)...
OKAY [ 1.036s]
writing 'cache'...
OKAY [ 0.380s]
finished. total time: 1.422s
C:\img files\android>
我如何在我的C代码中得到这个输出?你能试试这个简单的解决方案吗。我不知道在你的情况下能成功多少
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c ping 192.168.x.x"; //or your thing
p.Start();
string result = p.StandardOutput.ReadToEnd();
p.WaitForExit();
如果由于某种原因,缺少的信息被定义为fastboot中的错误,则RedirectStandardError应该解决它
var startInfo = new ProcessStartInfo("cmd.exe")
{
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
CreateNoWindow = true,
RedirectStandardError = true,
};
之后,您需要使用ErrorDataReceived事件来获取错误消息
cmd.ErrorDataReceived+=Cmd_OutputDataReceived
cmd.BeginErrorReadLine();
正如不信者@Damien_和@user2033402所建议的,出于某种原因,我需要的输出似乎被重定向到
StandardError
,而不是StandardOutput
因此,在我的案例中,有效的解决方案是以下代码:
private void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
var startInfo = new ProcessStartInfo("cmd.exe")
{
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
cmd = new Process { StartInfo = startInfo };
cmd.OutputDataReceived += Cmd_OutputDataReceived;
cmd.ErrorDataReceived += Cmd_ErrorDataReceived;
cmd.Start();
cmd.BeginOutputReadLine();
cmd.BeginErrorReadLine();
cmd.StandardInput.WriteLine($"cd {baseFolder}\\External Resources\\img files\\uboot");
string[] commands = CmdCommands.GetUbootFlashCommands();
foreach (var command in commands)
cmd.StandardInput.WriteLine(command);
cmd.StandardInput.WriteLine($"cd {baseFolder}\\External Resources\\img files\\android");
commands = CmdCommands.GetKernelFlashCommands();
foreach (var command in commands)
cmd.StandardInput.WriteLine(command);
cmd.StandardInput.WriteLine("exit");
cmd.WaitForExit();
}
private void Cmd_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Invoke(new Action(() =>
{
txtCmd.Text += e.Data + Environment.NewLine;
}));
}
private void Cmd_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
Invoke(new Action(() =>
{
txtCmd.Text += e.Data + Environment.NewLine;
}));
}
我想你可能想把启动的程序的标准输出导入你的控制台,其中一些可能会出现标准错误——其余的——它是否会随着进度而更新?可能是程序检测到它是否连接到终端,然后只显示该输出。@Marv:这是什么意思?你能发布一个代码样本吗?@Damien_不信者:为什么输出会变成
标准错误?为什么从C#运行cmd和手动运行cmd有什么区别?您只看到看到您看到的行,因为这就是您所做的全部工作—您将它们写入控制台。要接收已启动流程的输出,您必须将自己连接到它们并打印它们返回的内容。这通常是由控制台完成的,但在本例中,由于您负责控制台,因此不会发生这种情况。我尝试了它,但调用了StandardOutput.ReadToEnd()
,它会给出相同的输出,并等待所有过程完成,我希望在过程中显示输出。@LiranFriedman放置p.WaitForExit()
下面是读取输出,它应该可以工作!我已经编辑了我的答案,这无关紧要,因为代码在这里停止,比如string result=p.StandardOutput.ReadToEnd()代码>。需要向参数添加和退出命令,但它仍然提供相同的输出,因此也不需要这样做…我刚刚尝试了添加RedirectStandardError=true
并调用cmd.ErrorDataReceived+=cmd\u ErrorDataReceived代码>也是,但也没有输出…尝试使用cmd.StandardError.ReadToEnd()查看您缺少的是否真的是错误。如果不是,我不知道会是什么。好的luckoh wait“cmd.ErrorDataReceived+=cmd_ErrorDataReceived;”!=“cmd.ErrorDataReceived+=cmd_OutputDataReceived”我知道:“cmd.ErrorDataReceived+=cmd_ErrorDataReceived;”!=“cmd.ErrorDataReceived+=cmd\u OutputDataReceived”。在我的评论中,您可以看到我创建了一个新的方法:-)您认为cmd.StandardError.ReadToEnd()
与cmd.ErrorDataReceived
有什么不同吗?