C# 如何获得 System.Diagnostics.Process 的输出?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1390559/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get the output of a System.Diagnostics.Process?
提问by marcgg
I run ffmpeg like this:
我像这样运行ffmpeg:
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo = new System.Diagnostics.ProcessStartInfo(ffmpegPath, myParams);
p.Start();
p.WaitForExit();
... but the problem is that the console with ffmpeg pops up and disappears right away, so I can't get any feedback. I don't even know if the process ran correctly.
...但问题是带有ffmpeg的控制台弹出并立即消失,因此我无法获得任何反馈。我什至不知道该过程是否正确运行。
So how can I either:
那么我该怎么做:
Tell the console to stay opened
Retrieve in the C# what the console displayed
告诉控制台保持打开状态
在 C# 中检索控制台显示的内容
采纳答案by Lucas Jones
What you need to do is capture the Standard Output stream:
您需要做的是捕获标准输出流:
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
// instead of p.WaitForExit(), do
string q = "";
while ( ! p.HasExited ) {
q += p.StandardOutput.ReadToEnd();
}
You may also need to do something similar with StandardError
. You can then do what you wish with q
.
您可能还需要对StandardError
. 然后,您可以随心所欲地使用q
.
It is a bit finicky, as I discovered in one of my questions
正如我在我的一个问题中发现的那样,这有点挑剔
As Jon Skeet has pointed out, it is not smart performance-wise to use string concatenation like this; you should instead use a StringBuilder
:
正如 Jon Skeet 所指出的,像这样使用字符串连接在性能方面并不明智;你应该使用一个StringBuilder
:
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
// instead of p.WaitForExit(), do
StringBuilder q = new StringBuilder();
while ( ! p.HasExited ) {
q.Append(p.StandardOutput.ReadToEnd());
}
string r = q.ToString();
回答by Michael Vasquez
I know this question is old, but I'll add to it anyway.
我知道这个问题很老,但无论如何我都会补充。
If all you wish to do is display the output of a command line process, and you're spawning the process from a console window, you need only redirect the standard input (yes, I know it sounds wrong, but it works).
如果您只想显示命令行进程的输出,并且从控制台窗口生成该进程,则只需要重定向标准输入(是的,我知道这听起来不对,但确实有效)。
So:
所以:
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo = new System.Diagnostics.ProcessStartInfo(ffmpegPath, myParams);
p.UseShellExecute = false;
p.RedirectStandardInput = true;
p.Start();
p.WaitForExit();
Would do just fine.
会做得很好。
回答by Ben
For a more specific answer directly related to ffmpeg, passing the "-report" command into ffmpeg will make it dump a log into the current directory with what was said in the display of the process.
对于与 ffmpeg 直接相关的更具体的答案,将“-report”命令传递到 ffmpeg 将使其将日志转储到当前目录中,其中包含进程显示中所说的内容。
‘-report'
Dump full command line and console output to a file named program-YYYYMMDD-HHMMSS.log in the current directory. This file can be useful for bug reports. It also implies -loglevel verbose.
Note: setting the environment variable FFREPORT to any value has the same effect.
'-报告'
将完整的命令行和控制台输出转储到当前目录中名为 program-YYYYMMDD-HHMMSS.log 的文件中。此文件可用于错误报告。它还意味着 -loglevel 详细。
注意:将环境变量 FFREPORT 设置为任何值都具有相同的效果。
From FFMpeg Documentation.
来自FFMpeg 文档。
回答by chiccodoro
Lucas' answer has a race condition: If the process finishes quickly the while loop is left (or never entered) even if there is some output left, that is you might miss out on some data. To prevent that, another ReadToEnd
should be done afterthe process exited.
Lucas 的回答有一个竞争条件:如果进程很快完成,即使还有一些输出,也会留下(或从未进入)while 循环,也就是说你可能会错过一些数据。为了防止这种情况,ReadToEnd
应该在进程退出后做另一个。
(Note that in comparison to the old version of my answer, I can no longer see a need for WaitForExit
once the process.HasExited
flag is true, so this boils down to:)
(请注意,与我的答案的旧版本相比,WaitForExit
一旦process.HasExited
标志为真,我就不再需要,所以这归结为:)
using (var process = Process.Start(startInfo))
{
var standardOutput = new StringBuilder();
// read chunk-wise while process is running.
while (!process.HasExited)
{
standardOutput.Append(process.StandardOutput.ReadToEnd());
}
// make sure not to miss out on any remaindings.
standardOutput.Append(process.StandardOutput.ReadToEnd());
// ...
}