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?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With