• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 如何獲取子進程的輸出

    發表于:2007-05-25來源:作者:點擊數: 標簽:看到經常輸出獲取如何
    經??吹秸搲杏腥藛柕疆斢肞rocess組件啟動新的進程后,如何獲取它的輸出的問題。采取將子進程的輸出定向到一個臨時文件中,當然也可以解決問題。但是這樣每次父進程從臨時文件中獲取信息后,還要刪除該臨時文件,畢竟比較麻煩。其實,Process提供了幾個屬性


           經??吹?STRONG>論壇中有人問到當用Process組件啟動新的進程后,如何獲取它的輸出的問題。采取將子進程的輸出定向到一個臨時文件中,當然也可以解決問題。但是這樣每次父進程從臨時文件中獲取信息后,還要刪除該臨時文件,畢竟比較麻煩。其實,Process提供了幾個屬性可以獲取輸出。在.net框架sdk的幫助文檔里面就有這方面的例子,但是對于如何同時獲取錯誤輸出和標準輸出方面沒有給出具體代碼,本文將給出實例并對管道的特性作一些說明。

    一、獲取子進程標準輸出和錯誤輸出的的方法:
    我們寫一個小程序p2.cs,用它來產生標準輸出和錯誤輸出。
    //p2.cs代碼如下:
    using System;
    class class1
    {
     public static void Main()
     {
      int i = 0;
      string s1 = String.Format("out:{0,4}--------------------------------------------------",i);
      System.Console.Out.WriteLine(s1);
      string s2 = String.Format("err:{0,4}**************************************************",i);
      System.Console.Error.WriteLine(s2);
     }
    }
    編譯成p2.exe

    獲取子進程的標準輸出和錯誤輸出的源程序
    //p1.cs
    ....
    Process p = new Process("p2.exe");
    p.StartInfo.UseShellExecute = false;  //指定不使用系統的外殼程序,而是直接啟動被調用程序本身
    p.StartInfo.RedirectStandardOutput = true;  //只有將此屬性設為true,才能通過管道獲取子進程輸出
    p.StartInfo.RedirectStandardError = true;

    p.Start();  //啟動子進程
    string output = p.StandardOutput.ReadToEnd(); //讀取標準輸出
    string error = p.StandardError.ReadToEnd(); //讀取錯誤輸出
    p.WaitForExit(); //等待子進程執行完畢
    ...
      上例中,父進程啟動子進程后,就等待著從管道中取走標準輸出,取走全部標準輸出后取走錯誤輸出。我們運行起來沒有任何錯誤。但是一旦我門增加p2.exe中的標準輸出和錯誤輸出的字節數:
    for(i=0;i<200;i++)
     System.Console.Out.WriteLine(s1);
    for(i=0;i<200;i++)
     System.Console.Error.WriteLine(s2);
    編譯后,再運行,就會發現父進程和子進程出現了死鎖,只有強行關閉才能終止進程。

    二、管道:
     Process 組件通過管道與子進程進行通訊。如果同時重定向標準輸出和標準錯誤,然后試圖讀取它們,當管道被填滿時候就會出現問題。上例中,父進程只有讀完了所有的標準輸出才能讀錯誤輸出,而子進程的標準輸出每當把管道填滿時候,父進程都會取走,子進程接著向管道輸出后續的標準輸出。這都運行的很好??墒钱斪舆M程執行到輸出錯誤輸出的時候,由于子進程還沒有運行結束,它的標準輸出流就不會處于結束狀態(雖然在我們的例子中它的200次循環的標準輸出已經執行完畢),這就導致父進程中的ReadToEnd()方法不會執行完畢,所以父進程中的p.StandardError.ReadToEnd()無法執行,從而管道中的錯誤輸出無法被讀取,子進程的后續錯誤輸出無法寫入管道,最終子進程和父進程彼此無限等待,出現了阻塞情況。
     子進程通過檢查管道中最后一個字節是否被取走,來決定是否輸出后續內容。也就是說,如果管道緩沖區中最后一個字節之前的所有內容都被取走,子進程仍然會處于等待中;如果前面所有字節都沒有取走,但最后一個字節內容被取走,子進程會繼續向管道里輸出后續內容,當然這樣只能輸出一字節到管道中最后位置。
    我們如果把p1.cs中的string output = p.StandardOutput.ReadToEnd()改為:
     for(int i=0;i<200*60;i++)
      Console.Write((char) p.StandardOutput.Read());
    就不會出現死鎖情況。因為當獲取標準輸出的循環執行完后,會接著執行獲取錯誤輸出的語句,而不需等待標準輸出流的結束。但是這種方法毫無實際意義,因為實際中,我們并不可能像本例中知道標準輸出會有多少字節。

    三、用多線程分別獲取標準輸出和錯誤輸出
    對于這種情況,.net框架文檔中建議這樣解決:創建兩個線程,以便應用程序可以在單獨的線程上讀取每個流的輸出。下面給出例子:
    //p1.cs:
    ...
    class class1
    {
       .....
       public static void Main()
       {
     ProcessStartInfo pi = new ProcessStartInfo();
     pi.FileName = @"c:\p2.exe";
     pi.UseShellExecute = false;
     pi.RedirectStandardOutput = true;
     pi.RedirectStandardError = true;
     System.Diagnostics.Process p = new Process();
     p.StartInfo = pi;
     p.Start();
     tout t1 = new tout(p);
     terr t2 = new terr(p);
     Thread thread1 = new Thread(new ThreadStart(t1.Read));
     Thread thread2 = new Thread(new ThreadStart(t2.Read));
     thread1.Start();
     thread2.Start();
     p.WaitForExit();
     Console.WriteLine("p2.exe結束");
       }
    }
    class tout
    {
     Process p;
     public tout(Process p)
     {
      this.p = p;
     }
     public void Read()
     {
      int a = -1;
      while((a = p.StandardOutput.Read()) > 0)
      {
       Console.Write( ((char) a).ToString() );
      }
      Thread.CurrentThread.Abort();
      return;
     }
    }
    class terr
    {
     Process p;
     public terr(Process p)
     {
      this.p = p;
     }
     public void Read()
     {
      int a = -1;
      while((a = p.StandardError.Read()) > 0)
      {
       Console.Write(((char) a).ToString());
      }
      Thread.CurrentThread.Abort();
      return;
     }
    }

    原文轉自:http://www.kjueaiud.com

    評論列表(網友評論僅供網友表達個人看法,并不表明本站同意其觀點或證實其描述)
    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>