I'm attempting to redirect the output of a third party command line tool which is launched by my application. I am outputting to a rich text box. This is working successfully, with one exception.
When I test with a ping command, my output not formatted correctly. one line is appended to the previous. When I try to put a VbNewLine
in there or a VbCrLf
or a Environment.NewLine
is puts an extra blank line.
I get this output:
Pinging 8.8.8.8 with 32 bytes of data:
Reply from 8.8.8.8: bytes=32 time=29ms TTL=44
Reply from 8.8.8.8: bytes=32 time=29ms TTL=44
Reply from 8.8.8.8: bytes=32 time=30ms TTL=44
Reply from 8.8.8.8: bytes=32 time=29ms TTL=44
Ping statistics for 8.8.8.8:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 29ms, Maximum = 30ms, Average = 29ms
I want to get (as it is in a CMD window):
Pinging 8.8.8.8 with 32 bytes of data:
Reply from 8.8.8.8: bytes=32 time=31ms TTL=44
Reply from 8.8.8.8: bytes=32 time=29ms TTL=44
Reply from 8.8.8.8: bytes=32 time=29ms TTL=44
Reply from 8.8.8.8: bytes=32 time=29ms TTL=44
Ping statistics for 8.8.8.8:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 29ms, Maximum = 31ms, Average = 29ms
I'm sure it's very simple, but can't figure it out.
Here's the code I'm using.
Private Sub StartProcess()
Dim Proc = New Process()
Proc.StartInfo.FileName = "ping"
Proc.StartInfo.Arguments = "8.8.8.8"
Proc.StartInfo.RedirectStandardOutput = True
Proc.StartInfo.RedirectStandardError = True
Proc.EnableRaisingEvents = True
Application.DoEvents()
Proc.StartInfo.CreateNoWindow = True
Proc.StartInfo.UseShellExecute = False
AddHandler Proc.ErrorDataReceived, AddressOf proc_OutputDataReceived
AddHandler Proc.OutputDataReceived, AddressOf proc_OutputDataReceived
Proc.Start()
Proc.BeginErrorReadLine()
Proc.BeginOutputReadLine()
'Proc.WaitForExit()
End Sub
Delegate Sub UpdateTextBoxDelg(ByVal text As String)
Public myDelegate As UpdateTextBoxDelg = New UpdateTextBoxDelg(AddressOf UpdateTextBox)
Public Sub UpdateTextBox(ByVal text As String)
box_output.AppendText(text)
End Sub
Public Sub proc_OutputDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
On Error Resume Next
If Me.InvokeRequired = True Then
Me.Invoke(myDelegate, e.Data)
Else
UpdateTextBox(e.Data)
End If
End Sub
Bit of a stumper, took me a while. I noticed that e.Data can be Nothing, never seen that before. The network utilities are, erm, special, Berkeley is an unusual place on planet Earth.
You do have to add the line-ending yourself. Using InvokeRequired is pointless, it always is for the OutputDataReceived event. This version worked fine:
Public Sub proc_OutputDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
If e.Data IsNot Nothing Then Me.Invoke(myDelegate, e.Data + vbCrLf)
End Sub
Please use the System.Net.NetworkInformation.Ping class instead. It is not quite as affected by recreational chemical substances.