2009-06-29 60 views
1

我正在用C#編寫一個替換的Windows shell,而我當前實現的功能是將所有IO都放在同一個shell窗口中 - 即不在另一個窗口中打開cmd.exe。C#Shell - IO重定向

現在,我有一個輸出的部分解決方案。這是我的代碼(其中p是正在運行的進程):

while (!p.HasExited) { 
    /* ... - irrelevant */ 
    if (redirect) { 
     try { 
      p.BeginOutputReadLine(); 
     } catch { } 
    } 
} 

的過程建立與所有正確的屬性,如UseShellExecute = FalseRedirectStandard{Input, Output, Error} = True,以及事件處理程序的設置是否正確,但不一致。我試過拿出try/catch(我知道這是非常不好的做法),並且使用一個忙碌的布爾,當處理程序運行時它被設置爲false,但由於某種原因,我仍然得到一個InvalidOperationException on p.BeginOutputReadLine() - 聲明已經有一個異步操作正在運行。

任何幫助將不勝感激,即使它需要一個完全不同的解決方案,而不是僅僅修復它。

謝謝。

編輯:這是啓動過程的代碼:

if (redirect) 
{ 
    p.StartInfo.RedirectStandardOutput = true; 
    p.StartInfo.RedirectStandardError = true; 
    p.StartInfo.RedirectStandardInput = true; 
    p.StartInfo.UseShellExecute = false; 
    p.OutputDataReceived += new DataReceivedEventHandler(redirectHandler_StdOut); 
    p.ErrorDataReceived += new DataReceivedEventHandler(redirectHandler_StdErr); 
} 
p.Start(); 

另外,我意識到,我沒有解釋什麼,我的意思是不一致的。正如他們所說,一張圖片勝過2^3話:

screenshot

+0

啓動過程的代碼是什麼樣的? – 2009-06-29 22:22:04

+0

我現在就更新問題:) – 2009-06-29 22:24:16

回答

3

中的方法通常開始異步運行前綴。這是你想要的嗎?因爲看起來循環運行得儘可能快,所以調用越來越多的BeginOutputReadLine(因爲調用會立即返回,在它完成之前並且循環出現另一次迭代)。

您可以在StandardOutput流上調用ReadLine以獲得同步解決方案。或者:

while (!p.HasExited) { 
     /* ... - irrelevant */ 
     if (redirect && !busy) { 
      try { 
       busy = true; 
       p.BeginOutputReadLine(); 
      } catch { } 
     } 
    } 
    ////In the method that gets called upon completion of BeginOutputReadLine 
    busy = false; 

記住這雖然(從MSDN):

當異步讀取操作 開始,該事件處理程序每​​次相關的過程 稱爲 寫一行文本到其 StandardOutput流。

您可以通過調用CancelOutputRead來取消異步讀取 操作。 讀取操作可以通過調用者或事件處理程序取消 。 取消之後,您可以再次致電 BeginOutputReadLine,以恢復異步讀取操作的 。

這使我相信你應該只調用一次這個方法,並且它會在一行寫入時通過回調通知你。