我想知道是否有一种方法来触发一个事件,当一个设备被添加或从系统中删除。 我想能够检测是否说,一个USB闪存驱动器已被添加,或鼠标,或其他任何其他。 我试着四处搜寻,但是我找不到任何说的如何做到这一点。
有任何想法吗?
如果你的应用程序有一个窗口,你可以使用这样的东西:
using System; using System.Runtime.InteropServices; internal static class UsbNotification { public const int DbtDevicearrival = 0x8000; // system detected a new device public const int DbtDeviceremovecomplete = 0x8004; // device is gone public const int WmDevicechange = 0x0219; // device change event private const int DbtDevtypDeviceinterface = 5; private static readonly Guid GuidDevinterfaceUSBDevice = new Guid("A5DCBF10-6530-11D2-901F-00C04FB951ED"); // USB devices private static IntPtr notificationHandle; /// <summary> /// Registers a window to receive notifications when USB devices are plugged or unplugged. /// </summary> /// <param name="windowHandle">Handle to the window receiving notifications.</param> public static void RegisterUsbDeviceNotification(IntPtr windowHandle) { DevBroadcastDeviceinterface dbi = new DevBroadcastDeviceinterface { DeviceType = DbtDevtypDeviceinterface, Reserved = 0, ClassGuid = GuidDevinterfaceUSBDevice, Name = 0 }; dbi.Size = Marshal.SizeOf(dbi); IntPtr buffer = Marshal.AllocHGlobal(dbi.Size); Marshal.StructureToPtr(dbi, buffer, true); notificationHandle = RegisterDeviceNotification(windowHandle, buffer, 0); } /// <summary> /// Unregisters the window for USB device notifications /// </summary> public static void UnregisterUsbDeviceNotification() { UnregisterDeviceNotification(notificationHandle); } [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr RegisterDeviceNotification(IntPtr recipient, IntPtr notificationFilter, int flags); [DllImport("user32.dll")] private static extern bool UnregisterDeviceNotification(IntPtr handle); [StructLayout(LayoutKind.Sequential)] private struct DevBroadcastDeviceinterface { internal int Size; internal int DeviceType; internal int Reserved; internal Guid ClassGuid; internal short Name; } }
以下是您如何使用它从WPF窗口(Windows窗体是相似的):
protected override void OnSourceInitialized(EventArgs e) { base.OnSourceInitialized(e); // Adds the windows message processing hook and registers USB device add/removal notification. HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle); if (source != null) { windowHandle = source.Handle; source.AddHook(HwndHandler); UsbNotification.RegisterUsbDeviceNotification(windowHandle); } } /// <summary> /// Method that receives window messages. /// </summary> private IntPtr HwndHandler(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled) { if (msg == UsbNotification.WmDevicechange) { switch ((int)wparam) { case UsbNotification.DbtDeviceremovecomplete: Usb_DeviceRemoved(); // this is where you do your magic break; case UsbNotification.DbtDevicearrival: Usb_DeviceAdded(); // this is where you do your magic break; } } handled = false; return IntPtr.Zero; }
这里是Windows窗体的使用示例(更简单):
public Form1() { InitializeComponent(); UsbNotification.RegisterUsbDeviceNotification(this.Handle); } protected override void WndProc(ref Message m) { base.WndProc(ref m); if (m.Msg == UsbNotification.WmDevicechange) { switch ((int)m.WParam) { case UsbNotification.DbtDeviceremovecomplete: Usb_DeviceRemoved(); // this is where you do your magic break; case UsbNotification.DbtDevicearrival: Usb_DeviceAdded(); // this is where you do your magic break; } } }
接受的答案是优秀的,但它只适用于USB设备。
要使其适用于所有设备(并可选择过滤USB),请使用以下略有修改的类:
static class DeviceNotification { //https://msdn.microsoft.com/en-us/library/aa363480(v=vs.85).aspx public const int DbtDeviceArrival = 0x8000; // system detected a new device public const int DbtDeviceRemoveComplete = 0x8004; // device is gone public const int DbtDevNodesChanged = 0x0007; //A device has been added to or removed from the system. public const int WmDevicechange = 0x0219; // device change event private const int DbtDevtypDeviceinterface = 5; //https://msdn.microsoft.com/en-us/library/aa363431(v=vs.85).aspx private const int DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = 4; private static readonly Guid GuidDevinterfaceUSBDevice = new Guid("A5DCBF10-6530-11D2-901F-00C04FB951ED"); // USB devices private static IntPtr notificationHandle; /// <summary> /// Registers a window to receive notifications when devices are plugged or unplugged. /// </summary> /// <param name="windowHandle">Handle to the window receiving notifications.</param> /// <param name="usbOnly">true to filter to USB devices only, false to be notified for all devices.</param> public static void RegisterDeviceNotification(IntPtr windowHandle, bool usbOnly = false) { var dbi = new DevBroadcastDeviceinterface { DeviceType = DbtDevtypDeviceinterface, Reserved = 0, ClassGuid = GuidDevinterfaceUSBDevice, Name = 0 }; dbi.Size = Marshal.SizeOf(dbi); IntPtr buffer = Marshal.AllocHGlobal(dbi.Size); Marshal.StructureToPtr(dbi, buffer, true); notificationHandle = RegisterDeviceNotification(windowHandle, buffer, usbOnly ? 0 : DEVICE_NOTIFY_ALL_INTERFACE_CLASSES); } /// <summary> /// Unregisters the window for device notifications /// </summary> public static void UnregisterDeviceNotification() { UnregisterDeviceNotification(notificationHandle); } [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr RegisterDeviceNotification(IntPtr recipient, IntPtr notificationFilter, int flags); [DllImport("user32.dll")] private static extern bool UnregisterDeviceNotification(IntPtr handle); [StructLayout(LayoutKind.Sequential)] private struct DevBroadcastDeviceinterface { internal int Size; internal int DeviceType; internal int Reserved; internal Guid ClassGuid; internal short Name; } }
当调用RegisterDeviceNotification
(请参阅https://msdn.microsoft.com/en-us/library/aa363431(v=vs.85).aspx )时,关键更改是Flags
参数,如果设置为4
而不是0
则会忽略ClassGuid
参数并注册所有设备。