2009-06-24 79 views
4

我有一個窗體執行批處理文件。我想將我控制檯中發生的所有事情轉移到我的表單中的面板。我怎樣才能做到這一點?我的DOS控制檯如何與我的Windows窗體面板交流?C#Windows窗體.Net和DOS控制檯

感謝

回答

7

你可以調用從窗體應用程序的DOS或批處理程序和輸出重定向到一個字符串:

using (var p = new System.Diagnostics.Process()) 
{ 
    p.StartInfo.UseShellExecute = false; 
    p.StartInfo.RedirectStandardOutput = true; 
    p.StartInfo.FileName = PathToBatchFile; 
    p.StartInfo.Arguments = args; 
    p.Start(); 
    string o = p.StandardOutput.ReadToEnd(); 
    p.WaitForExit(); 
} 
+0

你可能想讀取從重定向輸出流輸入前行移動WaitForExit()調用。另外,如果需要,您可以添加WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden標誌,以防止控制檯應用程序出現,只要它不需要與用戶交互即可。 – LBushkin 2009-06-24 20:42:06

+0

謝謝...有沒有一種方法可以隱藏OS窗口?它現在正常工作,但顯示空的操作系統控制檯... – user62958 2009-06-24 22:35:33

1

我一直在用的System.Diagnostics.Process類鬼混用於調用基於控制檯的應用程序並格式化和返回輸出。我認爲它也可以用於批處理文件。我會在這裏花點時間來測試一下。這裏是一些示例代碼:

System.Diagnostics.ProcessStartInfo start = new System.Diagnostics.ProcessStartInfo(); 
    start.UseShellExecute = false; 
    start.RedirectStandardInput = true; 
    start.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; 

    start.RedirectStandardOutput = true; 
    start.FileName = "at"; 
System.Diagnostics.Process myP = System.Diagnostics.Process.Start(start); 
String strOutput = myP.StandardOutput.ReadToEnd(); 
if (strOutput.Contains("There are no entries in the list.")) 
{ 
    litMsg.Text = "There are no jobs"; 
} 
else 
{ 
    strOutput = strOutput.Replace("\r", ""); 
    foreach (String line in strOutput.Split("\n".ToCharArray())) 
    { 
     //(0,7) (7,5)(12, 24)    (36, 14)  (50,) 
     //Status ID Day      Time   Command Line 
     //------------------------------------------------------------------------------- 
     //  1 Tomorrow    3:00 AM  dir * 
     if (line.Length > 50) 
     { 
      String Status = line.Substring(0, 7); 
      String ID = line.Substring(7, 5); 
      String Day = line.Substring(12, 24); 
      String Time = line.Substring(35, 14); 
      String Command = line.Substring(49); 
     } 
    } 
} 
1

我最近建立一個小應用程序,我正在與批處理文件進行交互。我發現這個代碼的這段,讓我做到這一點:

Process proc = new Process 
       { 
        StartInfo = 
         { 
          RedirectStandardError = true, 
          RedirectStandardOutput = true, 
          UseShellExecute = false, 
         } 
       }; 
proc.Start(); 

string errorMessage = proc.StandardError.ReadToEnd(); 
proc.WaitForExit(); 
string outputMessage = proc.StandardOutput.ReadToEnd(); 
proc.WaitForExit(); 

從這裏,就直接這些字符串到您所選擇的用戶控件。


編輯

注意:這不是一個通用的解決方案。它可能導致死鎖。來自RedirectStandardError的文檔:
同步讀取操作在來自StandardError流的調用者讀取和寫入該流的子進程之間引入依賴關係。這些依賴關係可能導致死鎖情況。當調用者從子進程的重定向流中讀取時,它依賴於子進程。調用者等待讀取操作,直到孩子寫入流或關閉流。當子進程寫入足夠的數據以填充其重定向流時,它依賴於父進程。子進程等待下一個寫操作,直到父進程從完整流讀取或關閉流。當調用者和子進程等待彼此完成操作並且兩者都不能繼續時,將導致死鎖情況。您可以通過評估調用者和子進程之間的依賴關係來避免死鎖。

2

你應該通過增加System.Diagnostics的引用,然後調用批處理文件這樣開始:現在

string myFile = "c:\\path\\to\\batch_file.bat"; 
ProcessStartInfo psi = new ProcessStartInfo(myFile); 
psi.UseShellExecute = false; 
psi.CreateNoWindow = true; 
psi.RedirectStandardOutput = true; 
Process proc = Process.Start(psi); 

,如果你想呼叫被阻塞(IE,你的應用程序將凍結,直到文件完成),那麼只需使用string result = proc.StandardOutput.ReadToEnd()來讀取整個批處理文件的輸出。

但是,如果您希望應用程序能夠繼續響應以及實時顯示輸出,那麼您將需要使用BeginOutputReadLine

0

我敢肯定有更好的選擇,但你可以路由命令到一個臨時文件

Redirecting Command-Line Output to Files

的輸出程序,顯示大量 文字,考慮重定向文本 通常顯示在標準輸出到 文件。顯示大量的文字將會減慢執行速度 ;滾動文本 工作站上的終端窗口可能會導致I/O瓶頸(增加 已用時間)並使用更多的CPU時間。

以下命令顯示瞭如何通過 有效地運行 程序更重定向輸出到文件中,然後 顯示節目輸出:從程序

MYPROG> results.lis更results.lis 重定向輸出 將更改報告的時間,因爲 的屏幕I/O減少。

我想你可以將它路由到一個變量,但不是100%確定。可能有更好的選擇,但至少這是一個。

3

The doc states,如果你想讀都StandardError的和StandardOutput,你需要閱讀它們的至少一個異步爲了避免死鎖。另外,如果您在其中一個重定向流上調用ReadToEnd,則必須在調用WaitForExit()之前調用之前的。如果在ReadToEnd之前WaitForExit,輸出緩衝區可能會填滿,暫停進程,這意味着它永遠不會退出。這將是一個非常漫長的等待。這也是在文檔中!

例如:

string output; 
string error; 
System.Diagnostics.Process p = new System.Diagnostics.Process 
    { 
     StartInfo = 
     { 
      FileName = program, 
      Arguments = args, 
      WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden, 
      UseShellExecute = false, 
     } 
    }; 

if (waitForExit) 
{ 
    StringBuilder sb = new StringBuilder(); 
    p.StartInfo.RedirectStandardOutput = true; 
    p.StartInfo.RedirectStandardError = true; 
    Action<Object,DataReceivedEventArgs> stdErrorRead = (o,e) => 
    { 
     if (!String.IsNullOrEmpty(e.Data)) 
      sb.Append(e.Data); 
    }; 

    p.ErrorDataReceived += stdErrorRead; 
    p.Start(); 
    // begin reading stderr asynchronously 
    p.BeginErrorReadLine(); 
    // read stdout synchronously 
    output = p.StandardOutput.ReadToEnd(); 
    p.WaitForExit(); 
    // return code is in p.ExitCode 

    if (sb.Length > 0) 
     error= sb.ToString(); 

}