65.9K
CodeProject 正在变化。 阅读更多。
Home

用于检测 USB 设备的 USB 库

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (118投票s)

2010年2月22日

CPOL

3分钟阅读

viewsIcon

771701

downloadIcon

88551

一个用于检测 USB 设备并管理连接和断开事件的 USB 库

 

 

介绍 

这篇文章介绍了一个 USB 库,该库使您能够管理 USB 设备的连接和断开事件,并检测您自己的设备。我无法找到用 C# 编写的,并且在 Windows XP 和 Windows 7 x64 上都能运行的有效代码。因此,我决定编写自己的代码。我阅读了各种关于 USB 连接和断开检测的文章,并从 Microsoft 网站和 PINVOKE.NET 网站 ( http://www.pinvoke.net ) 获得了帮助。

此代码是一个单独的模块,您可以将其链接到您自己的项目中。该代码解释了如何添加其他属性。

Using the Code

更新您的代码

Windows 窗体 

  • 将引用添加到您的项目。
  • 在您的代码中添加 using 指令
    using USBClassLibrary;
  • 声明 USBClass 的实例。
    private USBClassLibrary.USBClass USBPort;
  • 如果您想读取设备的属性,请声明 DeviceProperties 的 List<T> 实例。
    private List<USBClassLibrary.USBClass.DeviceProperties> ListOfUSBDeviceProperties;
  • 创建 USBClass 类的实例。
    USBPort = new USBClass();
  • 创建 DeviceProperties 类的 List<T> 实例。
    ListOfUSBDeviceProperties = new List<USBClassLibrary.USBClass.DeviceProperties>();
  • USBClass 类公开的事件添加处理程序。
    USBPort.USBDeviceAttached += new USBClass.USBDeviceEventHandler(USBPort_USBDeviceAttached);
    USBPort.USBDeviceRemoved += new USBClass.USBDeviceEventHandler(USBPort_USBDeviceRemoved);
  • 注册您的窗体,以便在添加或删除设备时接收 Windows 消息。
    USBPort.RegisterForDeviceChange(true, this.Handle);
  • 然后,检查您的设备是否尚未连接
    if (USBClass.GetUSBDevice(MyDeviceVID, MyDevicePID, 
                 ref ListOfUSBDeviceProperties, false))
    {
       //My Device is connected
       MyUSBDeviceConnected = true;
    }
  • 实现连接和断开处理程序
    private void USBPort_USBDeviceAttached(object sender, 
                 USBClass.USBDeviceEventArgs e)
    {
       if (!MyUSBDeviceConnected)
       {
          if (USBClass.GetUSBDevice(MyDeviceVID, MyDevicePID, 
                                    ref ListOfUSBDeviceProperties, false))
          {
             //My Device is connected
             MyUSBDeviceConnected = true;
          }
       }
    }
    private void USBPort_USBDeviceRemoved(object sender, 
                 USBClass.USBDeviceEventArgs e)
    {
       if (!USBClass.GetUSBDevice(MyDeviceVID, MyDevicePID, 
                                  ref ListOfUSBDeviceProperties, false))
       {
          //My Device is removed
          MyUSBDeviceConnected = false;
       }
    }
  • 在您的窗体中处理 Windows 消息,以将它们传递给 USBClass
    protected override void WndProc(ref Message m)
    {
       bool IsHandled = false;
       USBPort.ProcessWindowsMessage(m.Msg, m.WParam, m.LParam, ref IsHandled);
       base.WndProc(ref m);
    }

WPF 

  • 将引用添加到您的项目。
  • 在您的代码中添加 using 指令
    using USBClassLibrary;
  • 声明 USBClass 的实例。
    private USBClassLibrary.USBClass USBPort;
  • 如果您想读取设备的属性,请声明 DeviceProperties 类的 List<T> 实例。
    private List<USBClassLibrary.USBClass.DeviceProperties> ListOfUSBDeviceProperties;
  • 创建 USBClass 类的实例。
    USBPort = new USBClass();
  • 创建 DeviceProperties 类的 List<T> 实例。
    ListOfUSBDeviceProperties = new List<USBClassLibrary.USBClass.DeviceProperties>(); 
  • 为 USBClass 类公开的事件添加处理程序。
    USBPort.USBDeviceAttached += new USBClass.USBDeviceEventHandler(USBPort_USBDeviceAttached);
    USBPort.USBDeviceRemoved += new USBClass.USBDeviceEventHandler(USBPort_USBDeviceRemoved);
  • 覆盖 OnSourceInitialized 以便
    • 检索 Windows 句柄
    • 添加一个事件处理程序,该处理程序接收所有窗口消息
    • 注册您的窗体,以便在添加或删除设备时接收 Windows 消息 
  • protected override void OnSourceInitialized(EventArgs e)
    {
       base.OnSourceInitialized(e);
       HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
       source.AddHook(WndProc);
       //USB Connection
       USBPort.RegisterForDeviceChange(true, source.Handle);
       USBTryMyDeviceConnection();
       MyUSBDeviceConnected = false;
    } 
  • 在您的窗体中处理 Windows 消息,以将它们传递给 USBClass 类
    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
       USBPort.ProcessWindowsMessage(msg, wParam, lParam, ref handled);
                
       return IntPtr.Zero;
    }
    
  • 然后,检查您的设备是否尚未连接
  • if (USBClass.GetUSBDevice(MyDeviceVID, MyDevicePID, 
                 ref ListOfUSBDeviceProperties, false))
    {
       //My Device is connected
       MyUSBDeviceConnected = true;
    }
  • 实现连接和断开处理程序
    private void USBPort_USBDeviceAttached(object sender, 
                 USBClass.USBDeviceEventArgs e)
    {
       if (!MyUSBDeviceConnected)
       {
          if (USBClass.GetUSBDevice(MyDeviceVID, MyDevicePID, 
                                    ref ListOfUSBDeviceProperties, false))
          {
             //My Device is connected
             MyUSBDeviceConnected = true;
          }
       }
    }
    private void USBPort_USBDeviceRemoved(object sender, 
                 USBClass.USBDeviceEventArgs e)
    {
       if (!USBClass.GetUSBDevice(MyDeviceVID, MyDevicePID, 
                                  ref ListOfUSBDeviceProperties, false))
       {
          //My Device is removed
          MyUSBDeviceConnected = false;
       }
    } 

获取与 USB 设备关联的 COM 端口

如果您的设备模拟串行端口,那么您可以检索其 COM 端口。

GetUSBDevice 函数有一个第四个参数 GetCOMPort

public static bool GetUSBDevice(UInt32 VID, UInt32 PID, ref List<deviceproperties> ListOfDP, bool GetCOMPort, Nullable<uint32> MI=null)

在您的连接代码中将其值设置为 True,并从 DeviceProperties 结构中检索 COM 端口

if (USBClass.GetUSBDevice(MyDeviceVID, MyDevicePID, 
             ref ListOfUSBDeviceProperties, true))
{
   String COMPort;
   //My Device is connected
   MyUSBDeviceConnected = true;
   COMPort = DP.COMPort;
}

编译

在项目属性的“生成”选项卡中,不要在“平台目标”下拉列表中选择“任何 CPU”,选择 x86 或 x64。

更新代码

如果您需要读取其他设备属性,只需按如下方式更新代码

  • 在 MSDN 中查找 SetupDiGetDeviceRegistryProperty 函数,并找到您要获取的属性。
  • DeviceProperties 添加一个新变量,该变量与您的属性的特征相匹配
    public struct DeviceProperties
    {
       public string FriendlyName;
       public string DeviceDescription;
       public string DeviceType;
       public string DeviceManufacturer;
       public string DeviceClass;
       public string DeviceLocation;
       public string DevicePath;
       public string DevicePhysicalObjectName;
       public string COMPort;
    }
  • 更新 GetUSBDevice 函数
    public static bool GetUSBDevice(UInt32 VID, UInt32 PID, ref List<deviceproperties> ListOfDP, bool GetCOMPort, Nullable<uint32> MI=null)
    {
       ...
        DP.DevicePhysicalObjectName = String.Empty;
        if (Win32Wrapper.SetupDiGetDeviceRegistryProperty(h, ref DevInfoData, 
          (UInt32)Win32Wrapper.SPDRP.SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, 
          ref RegType, intptrBuffer, BUFFER_SIZE, ref RequiredSize))
        {
          DP.DevicePhysicalObjectName = Marshal.PtrToStringAuto(intptrBuffer);
        }
        ...
    }

历史

  • 2010年2月22日
    • 文章首次发布
  • 2010年2月26日
    • 添加代码以检索与模拟串行端口的 USB 设备关联的 COM 端口
    • 相应地更新文档
  •  2013 年 11 月 17 日
    • 添加了对检测复合设备的支持,并修复了一个 DeviceProperties 字符串未正确初始化的错误。 
    • 通过添加“MI”字段更新了演示应用程序。
  • 2014 年 2 月 5 日
    • 添加了对 WPF 应用程序的支持:USB 类库被修改为删除对 Windows 窗体特定对象的任何引用。 
    • 该代码也在 Windows 8 和 Windows 8.1 上运行 
  • 2014 年 9 月 21 日
    • 添加了能够识别多个相同设备并返回 Device Properties 数组的功能。

 

 

© . All rights reserved.