2012-12-12 14 views
1

正如這裏所討論的ProcessStartInfo hanging on "WaitForExit"? Why? - 調用具有大輸出的p.WaitForExit()會填充OutputStream並導致死鎖,因爲進程和輸出流等待每個其他。使用RedirectStandardOutput處理大量的p.WaitForExit()輸出= True

我的示例代碼:

Dim p = New Process() 
Dim ReturnValue As Boolean = False 
p.StartInfo = New ProcessStartInfo(LynxPath, "-dump -nolist -width 1000 " & HtmlBuffer) 
p.StartInfo.WorkingDirectory = WorkingRoot 
p.StartInfo.UseShellExecute = False 
p.StartInfo.RedirectStandardOutput = True 
p.StartInfo.RedirectStandardError = True 
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden 
p.StartInfo.CreateNoWindow = True 
p.Start() 
ReturnValue = p.WaitForExit(5000) 

當與LYNX一個輸出大危在旦夕,除非我使用超時如上處理,當輸出緩衝區滿輸出修剪 - 這意味着任何輸出我讀不完整。

上述問題中發佈的c#解決方案似乎通過在進程類中使用OutputDataReceived事件來解決此問題。我的問題是不過是將C#代碼轉換成vb.net 3.5,我跑它通過正常的轉換路線和它吐出來:

Using process As New Process() 
    process.StartInfo.FileName = filename 
    process.StartInfo.Arguments = arguments 
    process.StartInfo.UseShellExecute = False 
    process.StartInfo.RedirectStandardOutput = True 
    process.StartInfo.RedirectStandardError = True 

    Dim output As New StringBuilder() 
    Dim [error] As New StringBuilder() 

    Using outputWaitHandle As New AutoResetEvent(False) 
     Using errorWaitHandle As New AutoResetEvent(False) 
      process.OutputDataReceived += Function(sender, e) 
      If e.Data Is Nothing Then 
       outputWaitHandle.[Set]() 
      Else 
       output.AppendLine(e.Data) 
      End If 

End Function 
      process.ErrorDataReceived += Function(sender, e) 
      If e.Data Is Nothing Then 
       errorWaitHandle.[Set]() 
      Else 
       [error].AppendLine(e.Data) 
      End If 

End Function 

      process.Start() 

      process.BeginOutputReadLine() 
      process.BeginErrorReadLine() 

       ' Process completed. Check process.ExitCode here. 
      If process.WaitForExit(timeout) AndAlso outputWaitHandle.WaitOne(timeout) AndAlso errorWaitHandle.WaitOne(timeout) Then 
       ' Timed out. 
      Else 
      End If 
     End Using 
    End Using 
End Using 

但是Visual Studio 2008和的標誌功能declerations爲無效的語法(聯方法如這是在4.5以後,我認爲?),如何在3.5中使用這個例子 - 不能讓我頭腦發熱。

編輯:剛剛發現這個鏈接:http://msdn.microsoft.com/en-us/library/system.diagnostics.process.outputdatareceived.aspx - 試圖弄清楚現在

+0

您可能會感興趣[此帖](HTTP://www.codeducky。 org/process-handling-net),它解釋瞭如何使用異步任務來處理進程流,而不是使用較爲笨拙的數據接受的事件 – ChaseMedallion

回答

0

這是我們ultimitly想出了,它需要一個HTML字符串,將其寫入到文件,然後用猞猁打開它,猞猁輸出,然後使用事件句柄(它處理大量輸出)抓獲,並填充一個純文本字符串:

Function ConvertHtmlToPlainText(ByVal HtmlString As String) As String 

    ' Define FileBuffer Path 
    Dim HtmlBuffer As String = WorkingRoot & "HtmlBuffer.html" 

    ' Delete any old buffer files 
    Try 
     If File.Exists(HtmlBuffer) = True Then 
      File.Delete(HtmlBuffer) 
     End If 
    Catch ex As Exception 
     Return "Error: Deleting old buffer file: " & ex.Message 
    End Try 

    ' Write the HTML to the buffer file 
    Try 
     File.WriteAllText(WorkingRoot & "HtmlBuffer.html", HtmlString) 
    Catch ex As Exception 
     Return "Error: Writing new buffer file: " & ex.Message 
    End Try 

    ' Check the file was written OK 
    If File.Exists(HtmlBuffer) = False Then 
     Return "Error: HTML Buffer file was not written successfully." 
    End If 

    If File.Exists(LynxPath) = False Then 
     Return "Error: Lynx.exe could not be found in path: " & LynxPath 
    End If 

    ' Read the buffer file with Lynx and capture plain text output 
    Try 
     LynxOutput = "" 
     LynxOutputLineCount = 0 
     Dim LynxProcess As New Process() 
     LynxProcess.StartInfo = New ProcessStartInfo(LynxPath, "-dump -nolist -width 1000 " & HtmlBuffer) 
     LynxProcess.StartInfo.UseShellExecute = False 
     LynxProcess.StartInfo.RedirectStandardOutput = True 
     LynxProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden 
     LynxProcess.StartInfo.CreateNoWindow = True 
     AddHandler LynxProcess.OutputDataReceived, AddressOf LynxOutputHandle 
     LynxProcess.StartInfo.RedirectStandardInput = True 
     LynxProcess.Start() 
     LynxProcess.BeginOutputReadLine() 
     LynxProcess.WaitForExit() 
     LynxProcess.Close() 

     ' Return the rendered Text 
     Return TrimEachLine(LynxOutput.Replace(vbLf & vbLf, vbLf)) 

    Catch ex As Exception 
     Return "Error: Error running LYNX to parse the buffer: " & ex.Message 
    End Try 
End Function 

Private Sub LynxOutputHandle(ByVal sendingProcess As Object, ByVal outLine As DataReceivedEventArgs) 
    LynxOutputLineCount = LynxOutputLineCount + 1 
    LynxOutput = LynxOutput & outLine.Data & vbLf 
End Sub