VB.NET重定向tshark捕获命令输出时,StreamReader.ReadLine的执行被卡住。
VB.NET重定向tshark捕获命令输出时,StreamReader.ReadLine的执行被卡住。
我正在尝试重定向我在VB.NET中编写的进程的标准
和错误
输出,其中我正在执行连续的命令。这是一个tshark命令(Wireshark的命令行工具),它可以在运行时捕获网络流量。我尝试了以下两个命令:
-i 5 -B 1 -w /sample.pcap --print -Tfields -e frame.number -e ip.addr -e tcp -e _ws.col.Info -E separator=/t
-i 10 -T fields -e dns.qry.name src port 53
这两个命令在命令提示符中都能正常工作。但是在代码中尝试重定向输出时,只有第一个命令能正常工作,而第二个命令在执行StreamReader.ReadLine
时卡住了。
请注意,我知道ReadLine
等待流中的新行被读取,而上述两个命令每捕获一个数据包就会生成一个新行的输出。我还尝试使用Read
和ReadBlock
(关于代码中需要进行的更改),但是对于第二个命令都没有起作用。
以下是我的代码:
Public Class Form1 Dim output As String Dim oProcess As New Process() Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Try Dim oStartInfo As New ProcessStartInfo("C:\Program Files\Wireshark\tshark.exe", "-i 10 -T fields -e dns.qry.name src port 53") oStartInfo.UseShellExecute = False oStartInfo.RedirectStandardOutput = True oStartInfo.RedirectStandardError = True oStartInfo.CreateNoWindow = True oStartInfo.WindowStyle = ProcessWindowStyle.Hidden oProcess.StartInfo = oStartInfo Catch ex As Exception MsgBox(ex) End Try BackgroundWorker1.RunWorkerAsync() Button1.Enabled = False Button2.Enabled = True End Sub Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork Try Threading.Thread.Sleep(2000) If oProcess.Start() Then Dim sOutput As String Using oStreamReader As System.IO.StreamReader = oProcess.StandardOutput sOutput = oStreamReader.ReadLine While Not sOutput Is Nothing output = sOutput & vbNewLine BackgroundWorker1.ReportProgress(10) sOutput = sOutput + vbNewLine + oStreamReader.ReadLine End While End Using Using oStreamReader As System.IO.StreamReader = oProcess.StandardError sOutput = oStreamReader.ReadLine While Not sOutput Is Nothing output = sOutput & vbNewLine BackgroundWorker1.ReportProgress(10) sOutput = sOutput + vbNewLine + oStreamReader.ReadLine End While End Using Else MsgBox("Error starting the process") End If Catch ex As Exception MsgBox(ex) End Try End Sub Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged TextBox1.Text = output TextBox1.Select(0, 0) End Sub Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click BackgroundWorker1.CancelAsync() Button1.Enabled = True Button2.Enabled = False End Sub Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load End Sub End Class
问题的原因是tshark输出是被缓存的,而不是由于VB.Net的问题。为了解决这个问题,可以在命令行中添加-tshark选项-l,以便在每个数据包打印后刷新标准输出。另外,还可以添加--print选项,以便在命令行中实时输出tshark的结果。
解决方法:
1. 在命令行中添加-tshark选项-l,以刷新标准输出:
tshark -l ...
2. 在命令行中添加--print选项,以实时输出tshark的结果:
tshark --print ...
以下是VB.Net代码的最终版本,其中已经添加了-tshark选项-l和--print选项:
Public Class Form1 Dim outputQueue As New Queue(Of String) Dim captureAdapterID As Integer = 0 Dim oProcess As Process Private Sub Button1_Click(sender1 As Object, e1 As EventArgs) Handles Button1.Click Button1.Enabled = False Button2.Enabled = True captureAdapterID = (ComboBox1.SelectedIndex + 1) BackgroundWorker1.RunWorkerAsync() End Sub Private Sub BackgroundWorker1_DoWork(sender1 As Object, e1 As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork Try oProcess = New Process() Dim oStartInfo As New ProcessStartInfo("C:\Program Files\Wireshark\tshark.exe", " --print -l -i " & captureAdapterID & " -w ./sample.pcap -E separator=/t -T fields -e frame.number -e dns.qry.name src port 53") oStartInfo.WorkingDirectory = New Uri(System.Windows.Forms.Application.StartupPath).LocalPath oStartInfo.UseShellExecute = False oStartInfo.RedirectStandardOutput = True oStartInfo.RedirectStandardError = True oStartInfo.CreateNoWindow = True oStartInfo.WindowStyle = ProcessWindowStyle.Hidden oProcess.StartInfo = oStartInfo If oProcess.Start() Then appendOutput("Capturing on device: " & captureAdapterID & " started.") Dim sOutput As String Using oStreamReader As System.IO.StreamReader = oProcess.StandardOutput sOutput = oStreamReader.ReadLine While Not sOutput Is Nothing appendOutput(sOutput) sOutput = oStreamReader.ReadLine End While End Using Using oStreamReader As System.IO.StreamReader = oProcess.StandardError sOutput = oStreamReader.ReadLine While Not sOutput Is Nothing appendOutput(sOutput) sOutput = oStreamReader.ReadLine End While End Using MsgBox("finished") Else MsgBox("Error starting the process") End If Catch ex As Exception MsgBox(ex.Message) Finally BackgroundWorker1.ReportProgress(10) End Try End Sub Private Sub appendOutput(sOutput As String) outputQueue.Enqueue(sOutput) BackgroundWorker1.ReportProgress(10) End Sub Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged Dim i As Integer = 0 For i = 0 To outputQueue.Count - 1 Step 1 RichTextBox1.AppendText(outputQueue.Dequeue & vbNewLine) Next RichTextBox1.ScrollToCaret() End Sub Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click BackgroundWorker1.CancelAsync() oProcess.Kill() Button1.Enabled = True Button2.Enabled = False End Sub Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Try Dim process As New Process() Dim oStartInfo As New ProcessStartInfo("C:\Program Files\Wireshark\tshark.exe", " -D") oStartInfo.WorkingDirectory = New Uri(System.Windows.Forms.Application.StartupPath).LocalPath oStartInfo.UseShellExecute = False oStartInfo.RedirectStandardOutput = True oStartInfo.RedirectStandardError = True oStartInfo.CreateNoWindow = True oStartInfo.WindowStyle = ProcessWindowStyle.Hidden process.StartInfo = oStartInfo If process.Start() Then Dim sOutput As String Using oStreamReader As System.IO.StreamReader = process.StandardOutput sOutput = oStreamReader.ReadToEnd If Not sOutput Is Nothing Then ComboBox1.Items.AddRange(sOutput.Trim.Split(vbNewLine)) Try ComboBox1.SelectedIndex = 0 Catch ex As Exception End Try End If End Using Else MsgBox("Error starting the get adapter process failed") End If Catch ex As Exception MsgBox(ex.Message) End Try End Sub End Class
文章结束。