1

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
NapkinBob
  • 632
  • 7
  • 19
  • I have deleted the answer because cannot address your problem if I cannot even understand what is the problem. I suggest you to do a proper debugging (line by line) to see what happens every time in order to come with a custom solution avoiding the duplicated lines. Other option might be doing a global replacement of duplicated newlines once the RTB has been populated; but again I don't know the exact conditions (a space between the duplicated new lines?) and thus cannot propose anything. This problem sounds unsolvable from my position, but pretty easy from yours. – varocarbas Nov 06 '13 at 22:24
  • Too bad. Even though it wasn't the answer, I would have marked it as useful, because it was. Thanks anyway for your efforts. – NapkinBob Nov 07 '13 at 13:51
  • No big deal. If I don't consider that my answer really addresses an issue what is the point of keeping it? I didn't have any idea why your code was outputting these results so... It would have been confusing for people looking for help with the same problem. Thanks for your intention though. – varocarbas Nov 07 '13 at 14:01

2 Answers2

3

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.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • In retrospect, perhaps using ping was a bad choice. I was only using that to test until I had built the rest of my code. (I have to build a custom string of arguments to pass to the process). Ping was the first thing I thought of that needed a command and arguments (literally the first thing) and would put out multiple lines of output. I failed to consider that ping was the problem. I guess I will finish the code and see how it works with the actual tool I need to use. I just figured that it should work, in theory. I'll try out what you suggest to simplify the invoke. – NapkinBob Nov 07 '13 at 13:51
0

Its working fine for me; simply modify your code as follows:

Public Sub UpdateTextBox(ByVal text As String)
    RichTextBox2.AppendText(text & System.Environment.NewLine)
End Sub

ScreenShot

Markus
  • 3,225
  • 6
  • 35
  • 47