2010-06-16 36 views
1

您能否解釋爲什麼shell重定向不能與System.Diagnostics.Process類一起使用?我正在嘗試使用以下代碼片段將輸出流重定向到文件:在c#中重定向標準輸出的問題

Process p = new Process(); 
p.StartInfo = new ProcessStartInfo(); 
p.StartInfo.FileName = "java.exe"; 
p.StartInfo.Arguments = @"> c:\Temp\test.log 2>&1"; 
p.StartInfo.UseShellExecute = true; 
p.Start(); 

類似的代碼在Python中沒有問題。 以編程方式讀取輸出流在我的情況下似乎不是一個可取的解決方案,因爲我的應用程序會啓動一堆進程。

回答

2

你不能做重定向,因爲沒有外殼直接參與。您可以運行cmd.exe會話,但正確的方法是使用RedirectStandardOutput/Error屬性。有很多過程時沒有問題。這是我爲此使用的課程。

class HandleExecutable { 
     private DataReceivedEventHandler outputHandler; 

     public DataReceivedEventHandler OutputHandler 
     { 
      set { outputHandler = value; } 
     } 
     private DataReceivedEventHandler errorHandler; 

     public DataReceivedEventHandler ErrorHandler 
     { 
      set { errorHandler = value; } 
     } 

     public void callExecutable(string executable, string args) 
     { 
      string commandLine = executable; 
      string args = args; 
      ProcessStartInfo psi = new ProcessStartInfo(commandLine); 
      psi.UseShellExecute = false; 
      psi.LoadUserProfile = false; 
      psi.RedirectStandardOutput = true; 
      psi.RedirectStandardError = true; 
      psi.WindowStyle = ProcessWindowStyle.Minimized; 
      psi.CreateNoWindow = true; 
      psi.Arguments = args; 
      p = new Process(); 
      p.StartInfo = psi; 
      try 
      { 
       p.Start(); 
       p.BeginOutputReadLine(); 
       p.BeginErrorReadLine(); 
       if (outputHandler != null) p.OutputDataReceived += outputHandler; 
       if (errorHandler != null) p.ErrorDataReceived += errorHandler; 
       p.WaitForExit(); 
       p.Close(); 
       p.Dispose(); 
      } 
      catch (Exception ex) 
      { 
       log.Error(ex.Message); 
      } 
     } 
    } 

    //On another class 
    void p_ErrorDataReceived(object sender, DataReceivedEventArgs e) 
    { 
     //HANDLE STDERR 
     if (e.Data != null && !e.Data.Equals("")) 
     { 
      if (!e.Data.Contains("Something")) { 
      } 
     } 
    } 

    void p_OutputDataReceived(object sender, DataReceivedEventArgs e) 
    { 
     //HANDLE STDOUT 
     if (e.Data != null && !e.Data.Equals("")) 
     { 
     } 
    } 

    HandleExecutable he = new HandleExecutable(); 
    he.OutputHandler = p_OutputDataReceived; 
    he.ErrorHandler = p_ErrorDataReceived; 
    he.callExecutable(@"C:\java.exe","-cp foo ClassName"); 
+0

理想情況下,您應該在開始閱讀之前設置事件處理程序。如果你不這樣做,你將有可能錯過輸出的第一位。有關示例,請參閱http://stackoverflow.com/questions/415620/redirect-console-output-to-textbox-in-separate-program-c-sharp – 2012-10-01 08:30:28

3

這是因爲沒有shell來處理這些參數。 當您將命令行鍵入shell時,它會被解析,程序參數與shell「特殊」修飾符分離,然後纔會啓動。 在C#中這不會發生,因爲沒有「cmd.exe」或「bash」過程來執行它。

要在C#中重定向輸入,您應該將p.StartInfo.RedirectStandardOutput設置爲true,然後使用p.StandardOutput來讀取數據,然後將其寫入文件。

或者,您可以運行帶有執行進程所需參數的「cmd.exe」並重定向其輸出。雖然不是跨平臺的,但這應該比自己編寫有效的數據流傳遞實現更容易。

+0

但我將ProcessStartInfo.UseShellExecute設置爲true,以便使用shell啓動進程。在這種情況下,ProcessStartInfo.UseShellExecute的含義是什麼? 謝謝! – Mher 2010-06-16 08:55:49

+0

@Mher http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.useshellexecute.aspx它大致相當於雙擊已註冊的文件,或者使用「start foo.doc」命令行 - 它爲給定的文件類型使用shell的處理程序。 – 2010-06-16 09:00:45

+0

'UseShellExecute = false'大致不允許進程在作爲域用戶的WindowsService環境中與文件系統交互 – 2012-10-03 14:20:05

0

如果您想重定向輸出流,您必須對其進行配置。設置Redirect...屬性並讀取流。你可以找到一個例子here

問候