2013-11-02 60 views
2

我正在通過c#Diagnostics.Process類調用一個exe文件,並從它的StdOut中讀取輸出。該過程的情況下,強制終止它不會自動在指定的時間結束,是這樣的:使用Process.kill異常終止進程後讀取StdOut

process.StartInfo.FileName = @"D:\t.exe"; 
process.StartInfo.RedirectStandardOutput = true; 
process.StartInfo.RedirectStandardError = true; 
process.StartInfo.RedirectStandardInput = false; 
process.StartInfo.UseShellExecute = false; 
process.StartInfo.CreateNoWindow = false; 

process.WaitForExit(500); 

if (!process.HasExited) 
{ 
    process.Kill(); 
    process.WaitForExit(); 
} 
string stdOutContents = process.StandardOutput.ReadToEnd(); 

現在的問題是代碼工作成功地當EXE正常終止。但是,如果它無法正常終止(通常exe被卡在一個無限循環的地方),stdOutContents被讀爲空字符串。

如何在進程被終止後不使用process.OutputDataReceived事件技術讀取StdOut? (已經證實,即使它在某處停留,問題中的exe文件也會將某些內容寫入到StdOut中)。約埃克


更新1

細節被調用(審閱橫跨這個問題, '原生應用')

它是一個小工具,用C語言實現並使用MS C++編譯器進行編譯。它在完成工作的同時將狀態信息輸出到StdOut(使用putchar)。

只有兩個操作的可能情況:

  1. 它會成功運行,同時打印一些數據到標準輸出。
  2. 它會正常運行到某個點(同時在StdOut上輸出數據),然後陷入無限循環。 (這是一個可以接受的行爲)。

這兩種情況都使用cmd驗證過。關於新的嘗試

細節我寫了一個C#應用程序(稱爲虛擬應用程序),它模仿的本機應用程序的行爲和該代碼工作正常。但是,當運行本機應用程序,我什麼也沒有得到。

我不明白爲什麼代碼不能讀取本地應用程序輸出的內容?

我也試過使用事件處理程序OutputDataReceived。它只會在代碼嘗試殺死進程時被args.Data = null調用一次。檢查虛擬應用程序的行爲顯示,當調用process.kill時,處理程序將調用args.Data = null。所以這似乎是兩種應用程序的標準行爲。

我也嘗試改變原生應用程序的換行符。由於它是用c語言實現的,因此它使用\ n作爲換行符。我嘗試使用兩個\ r \ n對換行,但StdOut仍然是空白的(案例2)。

+0

嗯......我用了一個無限循環,它每tms將一個值作爲t.exe寫入控制檯。它在這裏工作正常......您是否嘗試過使用事件處理程序進行調試?通過這種方式,您可以驗證該進程是否確實在其輸出流中寫入了某些內容。 –

回答

0

我有同樣的審訊和doc of Process.Kill

數據由過程或分配給進程的資源編輯可如果你打電話殺丟失。

這似乎表明,你不能靠閱讀過程的StandardOutput,雖然沒有明確指出輸出/錯誤流設置。

我終於得到了這個答案 How to spawn a process and capture its STDOUT in .NET?

啓發,我使用下面的代碼:

var info = new ProcessStartInfo("some.exe"); 
info.CreateNoWindow = true; 
info.RedirectStandardOutput = true; 
info.UseShellExecute = false; 

using (var p = new Process()) 
{ 
    p.StartInfo = info; 
    var output = new StringBuilder(); 
    p.OutputDataReceived += (sender, eventArgs) => 
    { 
     output.AppendLine(eventArgs.Data); 
    }; 
    p.Start(); 
    p.BeginOutputReadLine(); 
    if (!p.WaitForExit(5000)) 
    { 
     Console.WriteLine("Taking too long..."); 
     p.Kill(); 
     Console.WriteLine("Process killed, output :\n" + output); 
    } 
} 

同樣的模式可以使用的ErrorDataReceived

注意,一個可能錯過一些來自子進程的未被刷新的輸出,然而在我的情況下,我並不期望從一個需要被殺的進程得到很多信息,調試目的。