Reputation: 989
I'm trying to redirect the standard
and error
outputs of my process (written in VB.NET), where i'm executing a continuous command. It is a tshark command (a command line tool of Wireshark) that captures network traffic at runtime. I tried both of the following commands:
-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
Both commands works great in command prompt. However when trying to redirect the output in code, only command number 1 works while the second command stuck when executing StreamReader.ReadLine
.
Please note that i know that ReadLine
waits for a new line to be read by the stream, where both above commands generates a new line of output for each captured packet. I did also try using Read
and ReadBlock
(regarding needed changes in code) but none worked for the second command.
Here is my code:
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
Upvotes: 0
Views: 372
Reputation: 989
It was all a tshark
issue and never a VB.Net problem.
As mentioned by Mr.Kurt Knochner
when answering the question How to pipe tshark output in realtime?:
tshark output is buffered. Please use
tshark
option -l, if you want tshark to flush STDOUT after every packet.
And by referring to the documentation of tshark
here:
-l Flush the standard output after the information for each packet is printed.
So for making it working i added the --print
option along with the -l
to my command line and now it is working like a charm, where it now looks like:
tshark --print -l -i 10 -w ./sample.pcap -E separator=/t -T fields -e frame.number -e dns.qry.name src port 53
Here is my final version of code:
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
Upvotes: 1