【问题标题】:Problems getting desired output from Process.Start()从 Process.Start() 获取所需输出的问题
【发布时间】:2012-12-30 21:19:55
【问题描述】:

我正在开发一个应用程序,它调用多个命令行应用程序对某些视频文件进行一些后期处理。

现在我正在尝试使用Comskip 来识别来自我的有线卡调谐器的视频录制中的广告插播。这运行得很好,但是我在获取所需的屏幕输出时遇到了问题。

String stdout = null;

using (var process = new Process())
{
    var start = new ProcessStartInfo(comskip, cmdLine);

    start.WindowStyle = ProcessWindowStyle.Normal;
    start.CreateNoWindow = true;
    start.UseShellExecute = false;
    start.RedirectStandardOutput = true;

    process.StartInfo = start;

    process.Start();
    process.WaitForExit();

    stdout = process.StandardOutput.ReadToEnd();
}

我期待stdout 抓取屏幕上显示的内容,就像手动启动应用程序时一样(下面的屏幕截图),这是应用程序正在执行的操作的连续馈送,并混合在输出中给出百分比进度的行,我想用它来更新进度条

但是运行上面的代码只会给我:

使用的命令行是: "C:\Users\Chris\Google Drive\Tools\ComSkip\comskip.exe" "C:\Users\Chris\Desktop\ComSkip Tuning Files\Modern Family.wtv" "--ini=C:\Users\Chris\ Desktop\ComSkip Tuning Files\comskip_ModernFamily.ini"

根据命令行将 ini 文件设置为 C:\Users\Chris\Desktop\ComSkip Tuning Files\comskip_ModernFamily.ini 使用 C:\Users\Chris\Desktop\ComSkip Tuning Files\comskip_ModernFamily.ini 作为初始值。

我还尝试重定向StandardError 流并获取process.StandardError.ReadToEnd();,但如果我使用这些选项运行,该过程似乎会挂起。

我是否遗漏了一些东西来捕捉我想要的东西,或者这个应用程序的输出流是否有可能转到其他无法访问的地方?

【问题讨论】:

  • process.WaitForExit() 在进程完成之前不会返回,所以如果你想同步处理这一切,你需要一个 while (!_process.HastExited) _process.StandardOutput.ReadLine(); 一次读取一行。

标签: c# command-line


【解决方案1】:

您必须设置以下内容:

     process.StartInfo.RedirectStandardOutput = true;
     process.StartInfo.RedirectStandardError = true;
     process.StartInfo.UseShellExecute = false;
     process.OutputDataReceived += new DataReceivedEventHandler(ReadOutput);
     process.ErrorDataReceived += new DataReceivedEventHandler(ErrorOutput);

     process.Start();
     process.BeginOutputReadLine();
     process.BeginErrorReadLine();
     process.WaitForExit();

并在ReadOutputErrorOutput 中捕获输出

  private static void ErrorOutput(object sender, DataReceivedEventArgs e)
  {
     if (e.Data != null)
     {
        stdout = "Error: " + e.Data;
     }
  }

  private static void ReadOutput(object sender, DataReceivedEventArgs e)
  {
     if (e.Data != null)
     {
        stdout = e.Data;
     }
  }

【讨论】:

  • 我没有提到它,但我从OutputDataReceived 开始,我切换到同步方法,同时我试图找出哪个流包含我需要的数据....但我回去重试,还包括对ErrorDataReceived ...的支持,我找到了我的数据。不知道为什么同步方法不起作用,但你确实让我重新审视了我的解决方案。谢谢
  • @psubsee2003 欢迎您:)。两周前我在我的项目中使用了这段代码,并注意到,一些程序有时将正常消息显示为错误,将错误显示为正常消息,可能是来自 linux 的错误端口,它具有不同的返回码......
【解决方案2】:

请参阅 RedirectStandardOutput 上的 docs。在读取输出之前等待子进程结束可能会导致挂起。

特别是,这个例子说不要做你所做的事情:

 Process p = new Process();
 // Redirect the output stream of the child process.
 p.StartInfo.UseShellExecute = false;
 p.StartInfo.RedirectStandardOutput = true;
 p.StartInfo.FileName = "Write500Lines.exe";
 p.Start();
 // Do not wait for the child process to exit before
 // reading to the end of its redirected stream.
 // p.WaitForExit();
 // Read the output stream first and then wait.
 string output = p.StandardOutput.ReadToEnd();
 p.WaitForExit();

您应该使用事件OutputDataReceived 并可能使用ErrorDataReceived 并更新处理程序中的进度条。

【讨论】:

  • 感谢等待进程的建议。仅当我重定向StandardError 时,该应用程序才出现挂起的问题。当我只使用StandardOutput 时,它不会挂起。如果我将 StandardError.ReadToEnd() 调用移到 WaitForExit() 之前,我仍然会得到相同的行为。
  • 关于使用异步事件的建议,一旦我能够确定屏幕输出的位置,我计划将它们用于进度条。
猜你喜欢
  • 2016-03-13
  • 1970-01-01
  • 2021-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多