C# 从Process.Start()获取所需输出时出现问题

C# 从Process.Start()获取所需输出时出现问题,c#,command-line,C#,Command Line,我正在开发一个应用程序,它调用多个命令行应用程序对一些视频文件进行后期处理 现在,我正试图用我的有线电视卡调谐器识别视频录制中的商业中断。这运行得很好,但我在获取所需的屏幕输出时遇到了问题 String stdout = null; using (var process = new Process()) { var start = new ProcessStartInfo(comskip, cmdLine); start.WindowStyle = ProcessWindow

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

现在,我正试图用我的有线电视卡调谐器识别视频录制中的商业中断。这运行得很好,但我在获取所需的屏幕输出时遇到了问题

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\u ModernFamily.ini”

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

我还尝试重定向
StandardError
流并抓取
process.StandardError.ReadToEnd()但如果使用这些选项运行,进程将挂起

我是否错过了捕获我所希望的内容的内容,或者此应用程序的输出流是否可能转到其他不可访问的地方?

请参阅关于
重定向标准输出的部分。在读取输出之前等待子进程结束可能会导致挂起

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

 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
,并更新处理程序中的进度条。

请参阅上的
重定向标准输出。在读取输出之前等待子进程结束可能会导致挂起

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

 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
,并更新处理程序中的进度条。

您必须设置以下内容:

     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();
并在
ReadOutput
ErrorOutput

  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;
     }
  }

您必须设置以下内容:

     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();
并在
ReadOutput
ErrorOutput

  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;
     }
  }

感谢您提出的等待流程的建议。当我重定向
StandardError
时,应用程序才会出现挂起的问题。当我只使用
标准输出时,它不会挂起。如果我将
StandardError.ReadToEnd()
调用移动到
WaitForExit()
之前,我仍然会得到相同的行为。至于使用异步事件的建议,一旦我能够确定屏幕输出的方向,我计划将它们用于进度条。感谢您关于等待进程的建议。当我重定向
StandardError
时,应用程序才会出现挂起的问题。当我只使用
标准输出时,它不会挂起。如果我在
WaitForExit()
之前移动
StandardError.ReadToEnd()
调用,我仍然会得到相同的行为。至于使用异步事件的建议,我计划在确定屏幕输出的位置后,将它们用于进度条。我没有提到它,但是我从这一点开始,针对
OutputDataReceived
,我切换到了同步方法,同时我试图找出哪个流包含我需要的数据。。。。但我返回并重试了此操作,还包括对
ErrorDataReceived
的支持。。。我找到了我的数据。不知道为什么同步方法不起作用,但你确实让我重新审视了我的解决方案。Thanks@psubsee2003不客气:)。两周前我在我的项目中使用了这段代码,注意到有些程序有时会将正常消息显示为错误,将错误显示为正常消息,可能是来自linux的错误端口,它具有不同的返回代码…我没有提到它,但是我从这一点开始,针对
OutputDataReceived
,我切换到了同步方法,同时我试图找出哪个流包含我需要的数据。。。。但我返回并重试了此操作,还包括对
ErrorDataReceived
的支持。。。我找到了我的数据。不知道为什么同步方法不起作用,但你确实让我重新审视了我的解决方案。Thanks@psubsee2003不客气:)。两周前,我在我的项目中使用了这段代码,注意到有些程序有时会将正常消息显示为错误,将错误显示为正常消息,可能是来自linux的错误端口,它具有不同的返回代码…
process.WaitForExit()
在进程完成之前不会返回,因此如果您想同步处理这一切,您需要执行
while(!\u process.HastExited)\u process.StandardOutput.ReadLine()
一次读取一行。
process.WaitForExit()
在该过程完成之前不会返回,因此如果您想同步处理这一切,您需要在(!\u process.HastExited)\u process.StandardOutput.ReadLine()时执行
一次读取一行。