【问题标题】:VB.NET Redirecting tshark capture command output stuck at StreamReader.ReadLineVB.NET重定向tshark捕获命令输出卡在StreamReader.ReadLine
【发布时间】:2019-05-19 15:39:51
【问题描述】:

我正在尝试重定向我的进程的standarderror 输出(用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

这两个命令在命令提示符下都很好用。但是,当尝试在代码中重定向输出时,只有第 1 条命令有效,而第二条命令在执行 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

【问题讨论】:

  • 您不需要 BackgroundWorker。将异步(事件驱动)BeginOutputReadLine()BeginErrorReadLine()Exited 事件结合使用。示例代码here(输出到那里的 RichTextBox。当然,您可以更新任何其他控件)。
  • @Jimi 谢谢,我现在尝试了这个,它读取命令的前 3 行(这些行提示使用该捕获开始)并停止读取其他任何内容,我检查了 Exited 事件是否在没有被解雇的地方被解雇。我开始认为tshark 可能正在使用另一个输出编写器来打印数据包。你觉得呢?
  • 试试这个作为参数:"-i 10 -j ""http tcp ip"" -P -V"。您应该会看到大量信息流。
  • 然后试试:"-i 10 -T fields -e frame.number -e ip.addr -e udp -e _ws.col.Info -j ""http tcp ip"" -P -V"。之后缩小范围。您应该偶尔会看到一些信息。
  • @Jimi 两个命令的工作方式和你提到的完全一样,但是我的(命令号 2)仍然没有打印,有什么想法吗?

标签: c# vb.net tshark


【解决方案1】:

这完全是一个tshark 问题,而不是VB.Net 问题。 正如Mr.Kurt Knochner在回答问题How to pipe tshark output in realtime?时提到的那样:

tshark 输出被缓冲。如果需要,请使用tshark 选项 -l tshark 在每个数据包后刷新 STDOUT。

并参考tsharkhere的文档:

-l 在打印每个数据包的信息后刷新标准输出。

所以为了让它工作,我在命令行中添加了--print 选项和-l,现在它就像一个魅力一样工作,现在看起来像:

tshark --print -l -i 10 -w ./sample.pcap -E separator=/t -T fields -e frame.number -e dns.qry.name src port 53

这是我的最终版本代码:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-26
    • 2013-01-16
    • 1970-01-01
    • 2016-04-10
    相关资源
    最近更新 更多