C# 如何获取System.Diagnostics.Process的输出?

C# 如何获取System.Diagnostics.Process的输出?,c#,asp.net,windows,system.diagnostics,C#,Asp.net,Windows,System.diagnostics,我是这样运行ffmpeg的: System.Diagnostics.Process p = new System.Diagnostics.Process(); p.StartInfo = new System.Diagnostics.ProcessStartInfo(ffmpegPath, myParams); p.Start(); p.WaitForExit(); 。。。但问题是,带有ffmpeg的控制台会立即弹出并消失,因此我无法获得任何反馈。我甚至不知道这个过程是否正确运行 那么,我怎样

我是这样运行ffmpeg的:

System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo = new System.Diagnostics.ProcessStartInfo(ffmpegPath, myParams);
p.Start();
p.WaitForExit();
。。。但问题是,带有ffmpeg的控制台会立即弹出并消失,因此我无法获得任何反馈。我甚至不知道这个过程是否正确运行

那么,我怎样才能:

  • 告诉控制台保持打开状态

  • 在C#控制台中检索什么 展示


您需要做的是捕获标准输出流:

p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
// instead of p.WaitForExit(), do
string q = "";
while ( ! p.HasExited ) {
    q += p.StandardOutput.ReadToEnd();
}
您可能还需要使用
StandardError
执行类似的操作。然后,您可以使用
q
执行您想要的操作

正如我在书中发现的,这有点挑剔

正如Jon Skeet所指出的,像这样使用字符串连接是不明智的;您应该改为使用:


我知道这个问题很老,但我还是要补充一点

如果您只想显示命令行进程的输出,而您正在从控制台窗口生成该进程,则只需重定向标准输入(是的,我知道这听起来有误,但它可以工作)

因此:


很好。

对于与ffmpeg直接相关的更具体的答案,将“-report”命令传递到ffmpeg将使其将日志转储到当前目录中,并显示过程中所说的内容

“-报告”

将完整的命令行和控制台输出转储到名为 当前目录中的program-YYYYMMDD-HHMMSS.log。此文件可以是 对于bug报告很有用。它还意味着-loglevelverbose

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


From.

Lucas的答案有一个竞争条件:如果进程很快完成,则while循环将被保留(或从未进入),即使还有一些输出,也就是说,您可能会错过一些数据。为防止出现这种情况,应在进程退出后执行另一个
ReadToEnd

(请注意,与我的答案的旧版本相比,一旦
进程.HasExited
标志为真,我就不再需要
WaitForExit
,因此这归结为:)


对,基本的东西,但我不建议像那样构建字符串。使用StringBuilder:)实际上出现了一个错误:StandardOut尚未重定向或进程尚未启动。我在想到底发生了什么嗯。。。对此我不确定。如果您仍然有问题,请将代码发布到,我会看一看。这种方法有一个竞争条件:如果进程在您进入while循环之前结束,则不会读取输出。您没有添加太多内容,因为在已接受的答案中已经提到了。是我喝醉了,还是Michael Vasquez的名字和,真的,他的评论周围的大多数HTML都是向后的吗?这是因为在“was not.”之后有两个U+202E(从右到左的覆盖)序列编码在utf-8中,即0xe2 0x80 0xae 0xe2 0x80 0xae。我相信第一个示例会造成死锁情况。如果进程写入太多输出,它将阻止等待写入更多输出的机会。对于低于某个阈值的输出,这不会发生。如果它阻塞,它将永远被挂起。[直到被杀死]@Cameron-我已经更新了答案并删除了第一个代码片段。此外,在第二个代码片段中,我认为不再需要
WaitToExit
:一旦while循环离开,就意味着进程已经退出。但是我不确定你的要求。这意味着,即使在您对进程输出不感兴趣的情况下,您也必须始终添加一个while ReadToEnd结构,在代码中,您希望使用
process.start
启动进程,以确保进程不会在等待“空闲空间”时静止不动。我在帖子之后验证了我的声明。检查并查看。
ReadToEnd()
是同步的,如果重定向stdout但不从中读取,shell进程将暂停,并且进程将填充其输出缓冲区。另一方面,如果同时需要stdout和stderr,则需要对其中一个或两个都使用异步I/O。看见
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();
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();
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());

    // ...
}