Andrew Andrew - 3 months ago 23
C# Question

c# best way to ping lot of hosts

I tried to run CMD and got ping info from there:

ProcessStartInfo cmdStartInfo = new ProcessStartInfo();
cmdStartInfo.FileName = @"cmd";
cmdStartInfo.RedirectStandardOutput = true;
cmdStartInfo.RedirectStandardError = true;
cmdStartInfo.RedirectStandardInput = true;
cmdStartInfo.UseShellExecute = false;
cmdStartInfo.CreateNoWindow = true;

Process cmd = new Process();
cmd.StartInfo = cmdStartInfo;
cmd.ErrorDataReceived += DataReceived;
cmd.OutputDataReceived += DataReceived;
cmd.EnableRaisingEvents = true;
cmd.Start();
cmd.BeginOutputReadLine();
cmd.BeginErrorReadLine();

cmd.StandardInput.WriteLine("ping www.bing.com");
cmd.StandardInput.WriteLine("exit");

System.Threading.Thread.Sleep(4000);
cmd.WaitForExit();


Is exist some better way to do this?

Answer

Firstly make sure that you are really in need of opening a shell to process the commands. In your example it would be simpler just to run ping directly, for example,

ProcessStartInfo cmdStartInfo = new ProcessStartInfo()
{
    FileName = "ping",
    Arguments = "www.bing.com",
    RedirectStandardOutput = true,
    CreateNoWindow = true,
    UseShellExecute = false
};

Process proc = Process.Start(cmdStartInfo);
string reply = proc.StandardOutput.ReadToEnd();

Where ReadToEnd will wait until the process is finished before returning, giving you the whole output of the ping. ReadToEnd would also work for your example though instead of the Sleep.

I assume it's just a contrived example but if not, you don't need to use ping like this - .net provides the ping class which is easier to work with. For example.

private static void Ping(string address = "bing.com", int iterations = 4)
{
    Ping ping = new Ping();
    var hostEntry = Dns.GetHostEntry(address);

    byte[] buffer = new byte[32];
    new Random().NextBytes(buffer);

    Console.WriteLine("Pinging {0} [{1}] with {2} bytes of data:", hostEntry.HostName, hostEntry.AddressList[0], buffer.Length);

    for (int i = 0; i < iterations; i++)
    {
        PingReply reply = ping.Send(address, 1000, buffer);    
        Console.WriteLine("Reply from {0}: bytes={1}, time={2}ms, TTL={3}", reply.Address, reply.Buffer.Length, reply.RoundtripTime, reply.Options.Ttl);
    }
}

EDIT: to avoid hanging you could write it like this instead.

static void Main()
{
    Task<string> pingReply = RunCommand("ping", "bing.com");

    Console.WriteLine("I am waiting for ping to complete and could be doing something useful");

    pingReply.Wait();

    Console.WriteLine(pingReply.Result);
    Console.ReadKey();
}

public static Task<string> RunCommand(string command, string args)
{
    ProcessStartInfo cmdStartInfo = new ProcessStartInfo()
    {
        FileName = command,
        Arguments = args,
        RedirectStandardOutput = true,
        CreateNoWindow = true,
        UseShellExecute = false
    };

    Process proc = Process.Start(cmdStartInfo);        
    Task<string> readCommand = proc.StandardOutput.ReadToEndAsync();

    return readCommand;
}
Comments