Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to capture a serial port that disappears because the usb cable gets unplugged

I have a c# winforms program and it opens up a serial port. The problem happens when the end user unplugs the usb cable and then the device disappears. After this the program will crash and want to report the error to microsoft.

Is there a way to capture this event and shut down gracefully?

like image 744
Rex Logan Avatar asked Nov 13 '08 03:11

Rex Logan


2 Answers

Yes, there is a way to capture the event. Unfortunately, there can be a long delay between the time the device is removed and the time the program receives any notification.

The approach is to trap com port events such as ErrorReceived and to catch the WM_DEVICECHANGE message.

Not sure why your program is crashing; you should take a look at the stack to see where this is happening.

like image 199
jdigital Avatar answered Nov 09 '22 09:11

jdigital


You can use WMI (Windows Management Instrumentation) to receive notification on USB events. I did exactly that two years ago, monitoring for plugging and unplugging of a specific usb device.
Unfortunately, the code stays with my former employer, but I found one example at bytes.com:

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Management;
class UsbWatcher 
{
    public static void Main() 
    {
        WMIEvent wEvent = new WMIEvent();
        ManagementEventWatcher watcher = null;
        WqlEventQuery query;
        ManagementOperationObserver observer = new ManagementOperationObserver();

        ManagementScope scope = new ManagementScope("root\\CIMV2");
        scope.Options.EnablePrivileges = true; 
        try 
        {
            query = new WqlEventQuery();
            query.EventClassName = "__InstanceCreationEvent";
            query.WithinInterval = new TimeSpan(0,0,10);

            query.Condition = @"TargetInstance ISA 'Win32_USBControllerDevice' ";
            watcher = new ManagementEventWatcher(scope, query);

            watcher.EventArrived 
                += new EventArrivedEventHandler(wEvent.UsbEventArrived);
            watcher.Start();
        }
        catch (Exception e)
        {
            //handle exception
        }
}

I don't remember if I modified the query to receive events only for e specific device, or if I filtered out events from other devices in my event handler. For further information you may want to have a look at the MSDN WMI .NET Code Directory.

EDIT I found some more info on the event handler, it looks roughly like this:

protected virtual void OnUsbConnected(object Sender, EventArrivedEventArgs Arguments)
{
    PropertyData TargetInstanceData = Arguments.NewEvent.Properties["TargetInstance"];

    if (TargetInstanceData != null)
    {
        ManagementBaseObject TargetInstanceObject = (ManagementBaseObject)TargetInstanceData.Value;
        if (TargetInstanceObject != null)
        {
            string dependent = TargetInstanceObject.Properties["Dependent"].Value.ToString();
            string deviceId = dependent.Substring(dependent.IndexOf("DeviceID=") + 10);

            // device id string taken from windows device manager
            if (deviceId = "USB\\\\VID_0403&PID_6001\\\\12345678\"")
            {
                // Device is connected
            }
        }
    }
}

You may want to add some exception handling, though.

like image 32
Treb Avatar answered Nov 09 '22 08:11

Treb