0

On my way to learn C#, I created a winforms based application to ping google.com on the click of a button. So, when I click the button, the command prompt comes up but the ping command doesn't run and eventually the command prompt window exists after a while. What's wrong ? Why isn't the ping executing ?

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;

namespace WindowsFormsApplication1
 {
   public partial class Form1 : Form
   {
    public Form1()
    {
        InitializeComponent();
    }

    private void button_Click(object sender, EventArgs e)
    {
        Process p = new Process();
        p.StartInfo.FileName = "cmd.exe";

        p.StartInfo.Arguments = @"/C ping www.google.com";

        p.StartInfo.RedirectStandardOutput = true;

        p.StartInfo.UseShellExecute = false;

        p.Start();

        string output = p.StandardOutput.ReadToEnd();

        p.WaitForExit();

    }
}
}


CMD

CodeWalker
  • 2,281
  • 4
  • 23
  • 50

2 Answers2

3

You're using RedirectStandardOutput = true which means the output from the application is not outputted to console, but instead you have to read it, like you are doing at the end with string output =. In fact, if you debug your application you'll see the output from the application in your output variable.

If you set it to false the output will be displayed in the console window that pops up. Remember that you can't read from the StandardOutput if you do.

So it depends on what you want to do. Either

  • start the ping command directly and read its output, or
  • set RedirectStandardOutput = false and have the output from the command be displayed in its own window

On additional notes, if you have a textbox in your project named "hostBox" for instance, you can grab the text from the text box and ping that host instead, just set the arguments to the new host.

So the updated callback for the button will look like:

private void button_Click(object sender, EventArgs e) {
    Process p = new Process();
    p.StartInfo.FileName = "ping.exe";

    // you can put together any arguments you'd like in the string format call
    // for the moment only the text from hostBox is needed
    // for instance string.Format("{0} -t", hostBox.Text); if you want to ping indefinately
    p.StartInfo.Arguments = string.Format("{0}", hostBox.Text);
    p.StartInfo.CreateNoWindow = true;
    p.StartInfo.RedirectStandardOutput = true;
    p.StartInfo.UseShellExecute = false;

    p.Start();
    string output;
    // read output one line at the time. If the output is null, the application quit
    while ((output = p.StandardOutput.ReadLine()) != null) {
        textBox1.Text += output + Environment.NewLine;
        Application.DoEvents();
    }

    p.WaitForExit();
}

Also, note that I use ReadLine instead of ReadToEnd, this means that you don't have to wait for the application to end before getting the output. I also added a textBox1 in the form to append the text to from the application. The Application.DoEvents call makes sure the UI thread processes its events between each read line. Another option is to start the process in a new thread, and have the output be marshalled back with Invoke calls to the form.

Using threads can look something like this:

private void button_Click(object sender, EventArgs e) {
    new Thread(() => {

        Process p = new Process();
        p.StartInfo.FileName = "ping.exe";

        // you can put together any arguments you'd like in the string format call
        // for the moment only the text from hostBox is needed
        // for instance string.Format("{0} -t", hostBox.Text); if you want to ping indefinately
        p.StartInfo.Arguments = string.Format("{0}", hostBox.Text);
        p.StartInfo.CreateNoWindow = true;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.UseShellExecute = false;

        p.Start();
        string line;
        // read output one line at the time. If the output is null, the application quit
        while ((line = p.StandardOutput.ReadLine()) != null) {
            string output1 = line;
            textBox1.Invoke(new Action(() => {
                textBox1.Text += output1 + Environment.NewLine;
            }));
        }

        p.WaitForExit();
    }).Start();
}

The second option makes sure your UI will not freeze once you've clicked on the button and wait for the ping command to finish.

Patrick
  • 17,669
  • 6
  • 70
  • 85
  • 2
    Be careful with suggesting `Application.DoEvents()`...http://stackoverflow.com/questions/5181777/use-of-application-doevents – DonBoitnott Aug 23 '14 at 12:48
  • @DonBoitnott: Let the battle begin! :-P Good note with `DoEvents` btw, it's sort of the lazy mans tool. – Patrick Aug 23 '14 at 12:57
3

This line will keep you from seeing anything in the console:

p.StartInfo.RedirectStandardOutput = true;

That tells the Process that you intend to intercept the return data, which you seem to want to do:

String output = p.StandardOutput.ReadToEnd();

However, you do nothing with it. I changed to this and got a nice result:

Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;  //don't show the console at all
p.Start();
String output = p.StandardOutput.ReadToEnd();
String msg = "No result";
if (!String.IsNullOrEmpty(output))
    msg = output;
MessageBox.Show(msg);
DonBoitnott
  • 10,787
  • 6
  • 49
  • 68