Detecting network cable connect and disconnect in the Compact Framework

Today I got a question from a customer, that essentially was “how can I detect when the network cable has been plugged in or unplugged from my CF application.”  I knew I has solved this before, and after a little bit of digging with search engines I was reminded how obscrure finding the answer to this, even from native code, is.


So the general answer for how this is detected is that you have to call down into the NDIS driver via an IOCTL and tell it that you’re interested in notifications.  This is done with the IOCTL_NDISUIO_REQUEST_NOTIFICATION value.  Of course receiving the notifications isn’t so straightforward – you son’t just get some nice callback.  Instead you have to spin up a point to point message queue and send that in to the IOCTL call, along with a mask of which specific notifications you want.  Then, when something changes (like the cable is pulled) you’ll get an NDISUIO_DEVICE_NOTIFICATION structure on the queue, which you can then parse to find the adapter that had the event and what the exact event is.


From a managed code perspective, this is actually a lot of code to have to write – CreateFile to open NDIS, all of the queueing APIs, the structures for the notifications, etc.  Fortunately, I’d already been down this road and had added it to the Smart Device Framework already.  So if you’re using the SDF, getting the notifications looks like this:


public partial class TestForm : Form
{
  public TestForm()
  {
    InitializeComponent();

    this.Disposed += new EventHandler(TestForm_Disposed);

    AdapterStatusMonitor.NDISMonitor.AdapterNotification += new AdapterNotificationEventHandler(NDISMonitor_AdapterNotification);
    AdapterStatusMonitor.NDISMonitor.StartStatusMonitoring();
  }

  void TestForm_Disposed(object sender, EventArgs e)
  {
    AdapterStatusMonitor.NDISMonitor.StopStatusMonitoring();
  }

  void NDISMonitor_AdapterNotification(object sender, AdapterNotificationArgs e)
  {
    string @event = string.Empty;

    switch (e.NotificationType)
    {
      case NdisNotificationType.NdisMediaConnect:
        @event = “Media Connected”;
      break;
      case NdisNotificationType.NdisMediaDisconnect:
        @event = “Media Disconnected”;
      break;
      case NdisNotificationType.NdisResetStart:
        @event = “Resetting”;
      break;
      case NdisNotificationType.NdisResetEnd:
        @event = “Done resetting”;
      break;
      case NdisNotificationType.NdisUnbind:
        @event = “Unbind”;
      break;
      case NdisNotificationType.NdisBind:
        @event = “Bind”;
      break;
      default:
        return;
    }

    if (this.InvokeRequired)
    {
      this.Invoke(new EventHandler(delegate
      {
        eventList.Items.Add(string.Format(“Adapter ‘{0}’ {1}”, e.AdapterName, @event));
      }));
    }
    else
    {
      eventList.Items.Add(string.Format(“Adapter ‘{0}’ {1}”, e.AdapterName, @event));
    }
  }
}


 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s