2009-09-07 52 views
32

我运行的ffmpeg是这样的:如何获取System.Diagnostics.Process的输出?

System.Diagnostics.Process p = new System.Diagnostics.Process(); 
p.StartInfo = new System.Diagnostics.ProcessStartInfo(ffmpegPath, myParams); 
p.Start(); 
p.WaitForExit(); 

...但问题是,与ffmpeg的控制台弹出并消失向右走,所以我不能得到任何反馈。我甚至不知道过程是否正确运行。

所以,我怎么能之一:

  • 告诉控制台保持打开

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

回答

48

你需要做的是什么捕获标准输出流:

p.StartInfo.RedirectStandardOutput = true; 
p.StartInfo.UseShellExecute = false; 
// instead of p.WaitForExit(), do 
string q = ""; 
while (! p.HasExited) { 
    q += p.StandardOutput.ReadToEnd(); 
} 

您可能还需要执行类似于StandardError的操作。然后你可以用q做你想做的事。

这是一个有点挑剔,正如我在one of my questions

发现作为乔恩斯基特指出,这是不聪明的表现,明智的做法是使用字符串连接这样的;你应该使用一个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(); 
+4

右键基本的东西,但我不建议建立这样的字符串。使用StringBuilder :) – 2009-09-07 18:51:31

+0

谢谢,它看起来不错我现在要试试 – marcgg 2009-09-07 18:53:26

+1

实际上有一个错误:StandardOut没有被重定向或者进程​​尚未开始。我试图找出发生了什么 – marcgg 2009-09-07 18:54:52

3

我知道这个问题是旧的,但无论如何,我会添加到它。

如果您只想显示命令行进程的输出,并且您从控制台窗口产生进程,则只需重定向标准输入(是的,我知道它听起来不对,但它作品)。

所以:

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

会做得很好。

+0

你没有太多补充,因为这已经在接受的答案中提到。 – 2010-07-23 13:43:57

+0

不,它不是。 – 2010-08-21 10:19:45

+16

我喝醉了还是Michael Vasquez的名字,实际上,他的评论中的大部分HTML都是反向的? – 2011-01-14 04:21:52

4

对于与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.

FFMpeg Documentation

17

卢卡斯的答案有一个竞争条件:如果进程快速结束while循环离开(或从未进入),即使有一些输出,那么你可能会错过一些数据。为了防止这种情况,应该在退出后应该完成另一个ReadToEnd

(注意,与老版我的回答,我不能再认为有必要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()); 

    // ... 
} 
+0

我相信第一个例子会造成死锁情况。如果进程写入太多的输出,它将阻止等待机会写入更多的输出。输出低于某个阈值时不会发生这种情况。如果阻塞,它会永久挂起。 [直到遇难] – Cameron 2015-01-09 01:05:41

+0

@Cameron - 我已经更新了答案,并删除了第一个代码片段。此外,在第二个片段中,我不再需要'WaitToExit':一旦留下while循环,这意味着进程已经退出。但是我不确定你的说法。这意味着,即使在对流程输出不感兴趣的情况下,您仍然需要在代码中添加一个while-ReadToEnd结构,然后使用'Process.Start'开始一个流程,以确保过程不会停留在等待“自由空间”。 – chiccodoro 2015-01-09 11:43:14

+0

我在帖子后验证了我的声明。检查它并看看。 – Cameron 2015-01-09 18:09:00