VB.NET重定向tshark捕获命令输出时,StreamReader.ReadLine的执行被卡住。

19 浏览
0 Comments

VB.NET重定向tshark捕获命令输出时,StreamReader.ReadLine的执行被卡住。

我正在尝试重定向我在VB.NET中编写的进程的标准错误输出,其中我正在执行连续的命令。这是一个tshark命令(Wireshark的命令行工具),它可以在运行时捕获网络流量。我尝试了以下两个命令:

  1. -i 5 -B 1 -w /sample.pcap --print -Tfields -e frame.number -e ip.addr -e tcp -e _ws.col.Info -E separator=/t
  2. -i 10 -T fields -e dns.qry.name src port 53

这两个命令在命令提示符中都能正常工作。但是在代码中尝试重定向输出时,只有第一个命令能正常工作,而第二个命令在执行StreamReader.ReadLine时卡住了。

请注意,我知道ReadLine等待流中的新行被读取,而上述两个命令每捕获一个数据包就会生成一个新行的输出。我还尝试使用ReadReadBlock(关于代码中需要进行的更改),但是对于第二个命令都没有起作用。

以下是我的代码:

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

0
0 Comments

问题的原因是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

文章结束。

0