2013-03-26 98 views
2

我有一個程序(服務器),它將四行輸出打印到控制檯,然後開始監聽來自客戶端程序的傳入連接。從另一個程序讀取標準輸出

我有另一個程序(測試儀),我想從服務器讀取標準輸出並分析它。我已經安裝了測試程序來啓動服務器,並得到其輸出如下:

Process server = new Process(); 
server.StartInfo.FileName = "server.exe"; 
server.StartInfo.UseShellExecute = false; 
server.StartInfo.RedirectStandardInput = true; 
server.StartInfo.RedirectStandardOutput = true; 
server.StartInfo.RedirectStandardError = true; 
server.Start(); 
StreamReader serverOutput = server.StandardOutput; 
string line = serverOutput.ReadToEnd(); 
... 

我遇到的問題是,當我執行服務器自己(或當我與測試執行它不重定向輸出)我可以在控制檯上看到所有四行。但是,當我使用上面的代碼將服務器輸出重定向到測試程序時,測試程序掛在「ReadToEnd」命令上,就好像它正在等待來自服務器的更多輸出一樣。

我也嘗試使用「ReadLine」命令並將其放入一個FOR循環中重複4次。當我這樣做時,前三行輸出成功,然後掛在第4行「ReadLine」上,並且從不檢索第4行的服務器輸出。

最後,我也嘗試使用「讀取」命令嘗試逐個獲取字符,並且仍然無法從服務器輸出的第4行獲取任何字符。

任何有關我在這裏失蹤的建議?

更新: 經過大量的搜索後,我終於確定問題與輸出緩衝有關。服務器程序(用C++編寫)寫入cout,這似乎在打印到屏幕時自動刷新,但在將stdout重定向到測試程序時不會自動刷新。我可以將setvbuf(stdout, NULL, _IONBF, 0);添加到服務器程序中,以使標準輸出不被緩衝,但我更願意找到另一種不涉及更改服務器程序的解決方案。

+0

可能重複的[StandardOutput.ReadToEnd()掛起](http://stackoverflow.com/questions/7160187/standardoutput-readtoend-hangs) – 2013-03-26 17:55:10

回答

1

流結束時將返回ReadToEnd。當程序關閉時會發生這種情況。

您可以嘗試使用事件處理程序server.OutputDataReceived讀取數據。這樣你就可以異步接收它,而不會阻塞你的程序。

+0

事實上,我嘗試了異步第一(使用'server.OutputDataReceived' ),但它也不起作用。同樣的問題 - 它只挑選了前三行,並沒有顯示任何後續行。那時我開始嘗試同步。順便提一句,我確實想阻止我的程序(即服務器輸出一些值,然後測試者驗證寫入的內容,然後發送數據以使服務器繼續運行)。只是,無論我嘗試過什麼,我都無法讓測試者拿起三條以上的線。 – user2212659 2013-03-26 20:34:54

0

昨天我在試圖解決這個問題時發現了這個問題,所以我想我會用我找到的解決方案來回答它,只是爲了後人。

我遇到的問題是process.WaitForExit調用在完成讀取之前關閉輸出流。通過在調用WaitForExit之前在Tasks和Wait中運行ReadLine循環,我設法獲得所有輸出(在本例中爲Git調用)。

希望這有助於某人。的

var psi = new ProcessStartInfo(@"C:\Program Files (x86)\Git\bin\git.exe", "push " + remoteUrl + " " + branch) 
{ 
    UseShellExecute = false, 
    RedirectStandardOutput = true, 
    RedirectStandardError = true 
}; 

var process = new Process 
{ 
    StartInfo = psi 
}; 

Console.WriteLine("Pushing..."); 

process.Start(); 

var stdOutTask = Task.Factory.StartNew(() => 
{ 
    string str; 
    while ((str = process.StandardOutput.ReadLine()) != null) 
    { 
     Console.WriteLine(str); 
    } 
}); 
var stdErrorTask = Task.Factory.StartNew(() => 
{ 
    string str; 
    while ((str = process.StandardError.ReadLine()) != null) 
    { 
     Console.WriteLine(str); 
    } 
}); 

stdOutTask.Wait(); 
stdErrorTask.Wait(); 
process.WaitForExit(); 
process.Close(); 
相關問題