Thursday, May 15, 2008

Sending an ICMP packet to a remote server on the CF (Ping)

This question has been coming up a lot recently in the community "How do I ping a remote server from a device?".

I thought I'd write this quick article with some code in how to do this.

Even if you are using the latest version of the Compact Framework which is 3.5, there is no support for this without getting your hands dirty with native code.

A ping is essentially an Internet Control Message Protocol (ICMP) message and can be achieved from managed code by P/Invoking IcmpSendEcho2. This function can be found in Iphlpapi.dll and this call is supported on Windows CE 4.1 and later. For previous versions you'll need to link in library Icmplib.lib.

NOTE: If the machine is sitting behind a router (usual case), some routers give the option for blocking ICMP protocol, if the call doesn't work, you might want to check your router first.

Now this is the good part, instead of having to code the call to the IcmpSendEcho2 function yourself, OpenNETCF has kindly already provided a managed wrapper for us. The OpenNETCF Ping class can be found in the OpenNETCF.Net.NetworkingInformation namespace. Something like the following should work:

public static PingReply Ping(string ipAddress)
{
Cursor.Current = Cursors.WaitCursor;
Ping ping = new Ping();
PingReply reply = null;
try
{
reply = ping.Send(ipAddress, 10000);
switch (reply.Status)
{
case IPStatus.Success:
Cursor.Current = Cursors.Default;
if (ipAddress.IndexOf(".") > -1)
{
MessageBox.Show(string.Format(Properties.Resources.PingServerOK,
ipAddress,
reply.RoundTripTime),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Asterisk,
MessageBoxDefaultButton.Button1);
}
else
{
MessageBox.Show(string.Format(Properties.Resources.PingServerOK2,
ipAddress,
reply.RoundTripTime,
reply.Address.ToString()),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Asterisk,
MessageBoxDefaultButton.Button1);
}
break;
case IPStatus.BadDestination:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingBadDestination,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.BadOption:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingBadOption,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.BadRoute:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingBadRoute,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.DestinationHostUnreachable:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingDestinationHostUnreachable,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.DestinationNetworkUnreachable:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingDestinationNetworkUnreachable,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.DestinationPortUnreachable:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingDestinationPortUnreachable,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.DestinationProhibited:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingDestinationProhibited,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;

case IPStatus.DestinationScopeMismatch:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingDestinationScopeMismatch,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.DestinationUnreachable:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingPingDestinationUnreachable,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.HardwareError:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingHardwareError,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.IcmpError:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingIcmpError,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.NoResources:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingNoResources,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.PacketTooBig:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingPacketTooBig,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.ParameterProblem:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingParameterProblem,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.SourceQuench:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingDestinationScopeMismatch,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.TimedOut:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingTimeout,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.TimeExceeded:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingTimeExceeded,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.TtlExpired:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingTtlExpired,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.TtlReassemblyTimeExceeded:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingTtlReassemblyTimeExceeded,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.Unknown:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingUnknown,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
case IPStatus.UnrecognizedNextHeader:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingUnrecognizedNextHeader,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
default:
Cursor.Current = Cursors.Default;
MessageBox.Show(string.Format(Properties.Resources.PingUnknown,
ipAddress),
Properties.Resources.Ping,
MessageBoxButtons.OK,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
break;
}
}

catch (PingException ex)
{
Cursor.Current = Cursors.Default;
DialogResult result = MessageBox.Show(ex.Message,
Properties.Resources.Ping,
MessageBoxButtons.RetryCancel,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
if (result == DialogResult.Retry)
Ping(ipAddress);
}
catch (Exception ex)
{
DialogResult result = MessageBox.Show(ex.Message,
Properties.Resources.Ping,
MessageBoxButtons.RetryCancel,
MessageBoxIcon.Hand,
MessageBoxDefaultButton.Button1);
if (result == DialogResult.Retry)
Ping(ipAddress);
}
finally
{
Cursor.Current = Cursors.Default;
}
return reply;
}
That's all there is too it!

6 comments:

Anonymous said...

Simon,

Thanks for posting this code. I've been looking all over for a simple example of how to use the Ping class.

I keep getting a PingException "Impossible to send packet". I am very new to mobile and network programming, and cannot seem to find any help on this error. Do you have any suggestions as to where I might start looking? Thanks!

Simon Hart said...

Eric: The first thing to check is that you have network connectivity to your server that you are trying to ping. Try using pocket ie to do this. Also, if you are sitting behind a router, ensure the router has been enabled to accept ICMP packets.

Simon.

Artp said...

Working great. Thanks a lot :)

Ravi Ratan said...

This does not work when the device is on cradle or on emulator when it is cradle.

Any sugestion ?

Ravi Ratan said...

This does not work on device when placed on cradle to active sync.
OR An emulator when cradled.

Anonymous said...

I'm seeing the Impossible to send a packet error from my application, but when pinging from the wireless diagnostic tool on the device (Zebra MC3190-Z running Windows Embedded Handheld 6.5), it pings fine.

The application is a store & forward data collection application, that checks the network status (in WiFi) before attempting to connect to a SQL Server.

Thanks,
Erik
ejohnson@accessids.com