C#运行时获取进程输出

13
有没有办法重定向一个衍生进程的标准输出并在它发生时捕获它。我看到的所有内容都是在进程完成后使用ReadToEnd。我想要能够在输出正在打印时获取它。
编辑:
    private void ConvertToMPEG()
    {
        // Start the child process.
        Process p = new Process();
        // Redirect the output stream of the child process.
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.RedirectStandardOutput = true;
        //Setup filename and arguments
        p.StartInfo.Arguments = String.Format("-y -i \"{0}\" -target ntsc-dvd -sameq -s 720x480 \"{1}\"", tempDir + "out.avi", tempDir + "out.mpg");
        p.StartInfo.FileName = "ffmpeg.exe";
        //Handle data received
        p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived);
        p.Start();
    }

    void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        Debug.WriteLine(e.Data);
    }
2个回答

18
使用Process.OutputDataReceived事件从进程中接收所需的数据。
例如:
var myProc= new Process();

...            
myProc.StartInfo.RedirectStandardOutput = true;
myProc.OutputDataReceived += new DataReceivedEventHandler(MyProcOutputHandler);

...

private static void MyProcOutputHandler(object sendingProcess, 
            DataReceivedEventArgs outLine)
{
            // Collect the sort command output. 
    if (!String.IsNullOrEmpty(outLine.Data))
    {
      ....    
    }
}

1
是的,此外您还需要将 RedirectStandardOutput 设置为 true 才能使其正常工作。 - vcsjones
1
我尝试过了,但是没有什么运气。它可以正常运行,但回调函数从未被触发。也许输出方式存在问题。我正在使用ffmpeg。我将把我的代码添加到原始帖子中。 - thecaptain0220
4
启动进程后,我还需要添加myProc.BeginOutputReadLine(); - Markus
1
@lii dataReceivedEventHandler 的文档中提到:“当重定向的流被关闭时,会向事件处理程序发送一个空行。在访问 Data 属性之前,请确保您的事件处理程序检查此条件。例如,您可以使用静态方法 String.IsNullOrEmpty 来验证事件处理程序中的 Data 属性。” - RToyo
1
@RToyo 不应使用IsNullOrEmpty,因为null表示不继续,但在空行之后应继续处理。 - Sam Hobbs
显示剩余7条评论

8

所以经过进一步的挖掘,我发现FFmpeg使用stderr进行输出。以下是我修改后的代码以获取输出。

        Process p = new Process();

        p.StartInfo.UseShellExecute = false;

        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.RedirectStandardError = true;

        p.StartInfo.Arguments = String.Format("-y -i \"{0}\" -target ntsc-dvd -sameq -s 720x480 \"{1}\"", tempDir + "out.avi", tempDir + "out.mpg");
        p.StartInfo.FileName = "ffmpeg.exe";

        p.ErrorDataReceived += new DataReceivedEventHandler(p_ErrorDataReceived);
        p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived);

        p.Start();

        p.BeginErrorReadLine();
        p.WaitForExit();

很好的例子!不幸的是,它不能与p.StartInfo.UseShellExecute = true;一起使用(例如,在尝试捕获长时间运行的msbuild进程并实时在Visual Studio输出窗口中显示输出时)。 - gojimmypi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接