2015-12-20 25 views
0

在Form1構造如何在文本框中顯示一個過程StandardOutput?

cmd = " -i \"" + InputFile + "\" \"" + OutputFile + "\""; 
backgroundWorker1.RunWorkerAsync(); 

然後

private void ConvertNow(string cmd) 
     { 

      System.Diagnostics.Process proc = new System.Diagnostics.Process(); 
      proc.StartInfo.FileName = exepath; 
      proc.StartInfo.Arguments = cmd; 
      proc.StartInfo.UseShellExecute = false; 
      proc.StartInfo.CreateNoWindow = true; 
      proc.StartInfo.RedirectStandardOutput = true; 
      proc.Start(); 
      while (!proc.StandardOutput.EndOfStream) 
      { 
       string line = proc.StandardOutput.ReadLine(); 
       textBox1.Text = line; 
      } 
     } 
在DoWork的事件

然後

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
      ConvertNow(cmd); 
     } 

的問題是在該行中ConvertNow方法:

while (!proc.StandardOutput.EndOfStream) 

我使用了一箇中斷點,它已經到了,但是程序在這條線之後掛起,它永遠不會進入字符串和textBox行。

我該如何讓它可以在文本框中顯示輸出,或者在更好的控件中顯示richTextBox或者其他的東西?

這就是我現在嘗試:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
using System.IO; 
using System.Threading; 
using System.Diagnostics; 

namespace ConvertVideo 
{ 
    public partial class Form1 : Form 
    { 
     string InputFile = @"e:\lightningsmov\MVI_7909.MOV"; 
     string OutputFile = @"e:\lightningsmov\MVI_7909.mp4"; 
     string cmd; 
     string exepath = @"E:\myffmpegstatic\ffmpeg-20151217-git-9d1fb9e-win64-static\bin\ffmpeg.exe"; 
     FileInfo fi; 

     public Form1() 
     { 
      InitializeComponent(); 

      backgroundWorker1.WorkerReportsProgress = true; 
      backgroundWorker1.ProgressChanged += (sender, e) => textBox1.AppendText((string)e.UserState); 
      fi = new FileInfo(InputFile); 
      label2.Text = InputFile; 
      cmd = " -i \"" + InputFile + "\" \"" + OutputFile + "\""; 
      backgroundWorker1.RunWorkerAsync(); 
     } 

     private void ConvertNow(string cmd) 
     { 
      try 
      { 
       System.Diagnostics.Process proc = new System.Diagnostics.Process(); 
       proc.StartInfo.FileName = exepath; 
       proc.StartInfo.Arguments = cmd; 
       proc.StartInfo.UseShellExecute = false; 
       proc.StartInfo.CreateNoWindow = true; 
       proc.StartInfo.RedirectStandardOutput = true; 

       // use this event 
       proc.OutputDataReceived += (sender, e) => backgroundWorker1.ReportProgress(0, e.Data); // use this for synchronization 

       proc.Start(); 

       // and start asynchronous read 
       proc.BeginOutputReadLine(); 

       // wait until it's finished in your background worker thread 
       proc.WaitForExit(); 
      } 
      catch(Exception err) 
      { 
       string myerr = err.ToString(); 
      } 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 

     } 

     private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
      ConvertNow(cmd); 
     } 

     private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      textBox1.Text = e.ProgressPercentage.ToString(); 
     } 

     private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 

     } 
    } 
} 

當我使用就行了斷點:

proc.OutputDataReceived += (sender, e) => backgroundWorker1.ReportProgress(0, e.Data); 

並把我的鼠標移到PROC我裏面那個看到所有屬性具有相同例外:

BasePriority = 'proc.BasePriority' 扔 'System.InvalidOperationException' 類型

的一個異常

幾乎所有這些屬性。 試圖添加嘗試和捕捉,但它沒有得到抓住。

回答

0

你的代碼有幾個問題。最糟糕的是:你嘗試從不同於UI線程的線程更新控件。

我建議你改變你的ConvertNow方法如下:

private void ConvertNow(string cmd) 
{ 
    System.Diagnostics.Process proc = new System.Diagnostics.Process(); 
    proc.StartInfo.FileName = exepath; 
    proc.StartInfo.Arguments = cmd; 
    proc.StartInfo.UseShellExecute = false; 
    proc.StartInfo.CreateNoWindow = true; 
    proc.StartInfo.RedirectStandardOutput = true; 

    // use this event 
    proc.OutputDataReceived += (sender, e) => backgroundWorker1.ReportProgress(0, e.Data); // use this for synchronization 

    proc.Start(); 

    // and start asynchronous read 
    proc.BeginOutputReadLine(); 

    // wait until it's finished in your background worker thread 
    proc.WaitForExit(); 
} 

一個ProgressChanged事件添加到您的後臺工作(在例如表單構造):

backgroundWorker1.WorkerReportsProgress = true; 
backgroundWorker1.ProgressChanged += (sender, e) => textBox1.AppendText((string)e.UserState); 

所以,現在,只要您的進程寫入標準輸出,你會得到一個在UI線程上調用的事件並將數據附加到文本框中。

UPDATE:如果你已經有一個處理程序backgroundWorker1.ProgressChanged你不需要添加另一個,但可以在你的處理器直接插入該行textBox1.AppendText((string)e.UserState);。但是如果您從其他部分調用backgroundWorker1.ReportProgress作爲我,您應該首先檢查e.UserState是否應該添加到文本框中。

+0

無法發現錯誤,它在我這裏工作正常。也許這是你開始進程的二進制文件的問題?它輸出的東西標準輸出嗎?也許它使用stderr? (順便說一句:讓我們來清理這些評論,這不應該是一個聊天) –

+0

我測試了我現在看到的行:proc.OutputDataReceived + =(sender,e)=> backgroundWorker1.ReportProgress(0,e.Data);所有屬性出錯:StandardOutput ='proc.StandardOutput'引發了類型爲「系統」的異常。InvalidOperationException'在proc的所有屬性上出現相同的異常錯誤 –

+0

好吧,讓我在問題中再次添加我的代碼,就像它現在一樣。我會在後臺工程的設計人員那裏補充一點,我在那裏刪除了progresschanged事件,我只通過構造函數使用你的行註冊了它,所以不會有錯誤。 –

相關問題