用于检测 USB 设备的 USB 库
一个用于检测 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 数组的功能。