如何捕获因USB电缆拔出而消失的串口

Rex*_*gan 7 c# serial-port winforms

我有一个ac#winforms程序,它打开了一个串口.当最终用户拔下USB电缆然后设备消失时,就会出现问题.在此之后,程序将崩溃,并希望将错误报告给microsoft.

有没有办法捕获此事件并优雅地关闭?

jdi*_*tal 8

是的,有一种方法来捕捉事件.不幸的是,在删除设备和程序收到任何通知的时间之间可能会有很长的延迟.

该方法是捕获诸如ErrorReceived之类的com端口事件并捕获WM_DEVICECHANGE消息.

不确定你的程序崩溃的原因; 你应该看看堆栈,看看发生了什么.


Tre*_*reb 5

您可以使用WMI(Windows Management Instrumentation)接收有关USB事件的通知.两年前我完成了这项工作,监控特定USB设备的插拔.
不幸的是,代码留在我的前雇主,但我在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
        }
}
Run Code Online (Sandbox Code Playgroud)

我不记得我是否修改了查询以仅接收特定设备的事件,或者我是否从事件处理程序中的其他设备中过滤掉了事件.有关详细信息,您可能需要查看MSDN WMI .NET代码目录.

编辑 我在事件处理程序上找到了更多信息,它看起来大致如下:

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
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,您可能希望添加一些异常处理.