1

I have a textbox and a button. The button invokes Ping() and I want any progress of ping to be displayed in textBox1.

        void Ping()
        {
            p = new Process();
            p.StartInfo.FileName = "ping";
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.Arguments = "www.microsoft.com";
            p.Start();
            textBox1.Text = p.StandardOutput.ReadToEnd();
            p.WaitForExit();
        }

How to achieve it? The current implementation I wrote above does not show the progress but the final output.

kiss my armpit
  • 3,413
  • 1
  • 27
  • 50

2 Answers2

6
async void Test()
{
    await Ping("www.google.com");
}


Task Ping(string host)
{
    var tcs = new TaskCompletionSource<object>();

    ProcessStartInfo psi = new ProcessStartInfo();
    psi.FileName = "ping.exe";
    psi.UseShellExecute = false;
    psi.RedirectStandardOutput = true;
    psi.Arguments = host;

    var proc = Process.Start(psi);

    proc.OutputDataReceived += (s, e) => {
            Action action = () => textBox1.Text += e.Data + Environment.NewLine;
            this.Invoke(action);
        };

    proc.Exited += (s, e) => tcs.SetResult(null);

    proc.EnableRaisingEvents = true;
    proc.BeginOutputReadLine();

    return tcs.Task;
}

RESULT

Pinging www.google.com [64.15.117.154] with 32 bytes of data:
Reply from 64.15.117.154: bytes=32 time=50ms TTL=55
Reply from 64.15.117.154: bytes=32 time=45ms TTL=55
Reply from 64.15.117.154: bytes=32 time=45ms TTL=55
Reply from 64.15.117.154: bytes=32 time=46ms TTL=55

Ping statistics for 64.15.117.154:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 45ms, Maximum = 50ms, Average = 46ms

Having said that, I would use the Ping class instead of launching an external application

var ping = new System.Net.NetworkInformation.Ping();
var pingReply = await ping.SendPingAsync("www.google.com");
Console.WriteLine("{0} {1} {2}",pingReply.Address, 
                                pingReply.RoundtripTime, 
                                pingReply.Status);
EZI
  • 15,209
  • 2
  • 27
  • 33
4

Update

After receiving QtX comment, I went ahead and re-did the entire project in WinForms.

Here's the updated code and a screenshot, hope this helps you.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {  
        private Process p;

        public Form1()
        {
            InitializeComponent();

        }

        private void cmdPing_Click(object sender, EventArgs e)
        {
            p = new Process();
            startNewThread();
        }

        public void Log(string line)
        {
            txtOutput.Text += line + System.Environment.NewLine;
        }

        private void startNewThread()
        {
            Thread x = new Thread(new ThreadStart(Ping));
            x.IsBackground = true;
            x.Start();
        }

        private void Ping()
        {
            p.StartInfo.FileName = "ping.exe";
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.Arguments = txtAddress.Text;
            p.Start();

            while (p.StandardOutput.Peek() > -1)
            {
                this.Invoke((MethodInvoker)delegate() { Log(p.StandardOutput.ReadLine()); });
                p.StandardOutput.DiscardBufferedData();
            }

        }

    }
}

Screenshot of Form

enter image description here

Community
  • 1
  • 1
Dayan
  • 7,634
  • 11
  • 49
  • 76
  • 1
    Replaceing `Console.WriteLine` with `TextBox.Text` wouldn't work. I will throw `InvalidOperationException` because of *cross thread access* to UI components. – EZI Feb 25 '14 at 17:29
  • @QtX Good point, in that case the OP can return an List of strings that he can then iterate over to populate the Textbox. Or use a Delegate to populate the Textbox as the messages come in. Thank you for pointing that out. – Dayan Feb 25 '14 at 17:44
  • @QtX Updates my answer with the changes. – Dayan Feb 25 '14 at 18:25