如何获得系统、诊断、过程的输出?

时间:2022-08-29 14:54:30

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#中检索控制台显示的内容。

4 个解决方案

#1


48  

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();

#2


17  

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 after the 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:)

(请注意,与旧版本的答案相比,我不再认为有必要在这个过程中等待退出。已经退出的标志是正确的,所以这归结为:)

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());

    // ...
}

#3


4  

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.

将完整的命令行和控制台输出转储到名为program- yyymmdd - hhmmss的文件中。登录当前目录。这个文件对于错误报告很有用。它也意味着-loglevel verbose。

Note: setting the environment variable FFREPORT to any value has the same effect.

注意:将环境变量FFREPORT设置为任何值具有相同的效果。

From FFMpeg Documentation.

从FFMpeg文档。

#4


3  

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.

就做的很好。

#1


48  

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();

#2


17  

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 after the 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:)

(请注意,与旧版本的答案相比,我不再认为有必要在这个过程中等待退出。已经退出的标志是正确的,所以这归结为:)

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());

    // ...
}

#3


4  

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.

将完整的命令行和控制台输出转储到名为program- yyymmdd - hhmmss的文件中。登录当前目录。这个文件对于错误报告很有用。它也意味着-loglevel verbose。

Note: setting the environment variable FFREPORT to any value has the same effect.

注意:将环境变量FFREPORT设置为任何值具有相同的效果。

From FFMpeg Documentation.

从FFMpeg文档。

#4


3  

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.

就做的很好。