Windows环境下通过PowerShell监控新USB设备连接
监控USB设备连接的可行方案
方案1:WMI事件订阅(推荐,轻量易实现)
利用Windows Management Instrumentation (WMI)的__InstanceCreationEvent事件,针对Win32_PnPEntity类筛选USB设备,实现事件驱动式监控,无需轮询。
示例PowerShell脚本
# 注册USB设备连接事件订阅 Register-WmiEvent -Query @" SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_PnPEntity' AND TargetInstance.PNPClass='USB' "@ -Action { $device = $event.SourceEventArgs.NewEvent.TargetInstance # 按需处理设备属性,以下为示例输出 Write-Host "=== 新USB设备已连接 ===" Write-Host "设备名称: $($device.Name)" Write-Host "设备ID: $($device.DeviceID)" Write-Host "硬件ID: $($device.HardwareID -join '; ')" Write-Host "PNP类别: $($device.PNPClass)" } -SourceIdentifier "USBDeviceMonitor"
持久化方法
- 将脚本保存为
USBMONITOR.ps1,创建任务计划:设置开机触发,以管理员权限运行powershell.exe -ExecutionPolicy Bypass -File "C:\路径\USBMONITOR.ps1" - 若需永久订阅(重启后保留),可使用
Register-CimIndicationEvent替代Register-WmiEvent,并添加-Persistent $true参数(需WMI命名空间权限)
方案2:DevCon命令行工具轮询
微软官方的DevCon工具可枚举系统硬件设备,通过定时对比设备列表实现监控,适合简单场景。
实现步骤
- 下载对应系统版本的DevCon工具(包含在Windows SDK中)
- 编写PowerShell脚本定期枚举USB设备并对比:
$currentDevices = devcon find *usb* | Out-String $lastDevices = Get-Content -Path "C:\USBDevicesLast.txt" -ErrorAction SilentlyContinue # 对比找出新增设备 if ($currentDevices -ne $lastDevices) { $newDevices = Compare-Object -ReferenceObject $lastDevices -DifferenceObject $currentDevices | Where-Object SideIndicator -eq '=>' if ($newDevices) { Write-Host "=== 检测到新USB设备 ===" $newDevices.InputObject | ForEach-Object { Write-Host $_ } } # 更新上次设备列表 $currentDevices | Set-Content -Path "C:\USBDevicesLast.txt" }
- 创建任务计划,设置重复触发(如每10秒一次),运行该脚本
方案3:Windows服务+设备通知API(底层可控)
通过Windows API RegisterDeviceNotification监听WM_DEVICECHANGE消息,实现最底层的设备事件监控,支持所有USB设备类型(包括非存储类),适合需要精细控制的场景。
C#服务核心代码示例
using System; using System.Runtime.InteropServices; using System.ServiceProcess; public class USBDeviceMonitorService : ServiceBase { private IntPtr _notificationHandle; // Windows API声明 [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, IntPtr NotificationFilter, uint Flags); [DllImport("user32.dll", SetLastError = true)] private static extern bool UnregisterDeviceNotification(IntPtr Handle); private const int WM_DEVICECHANGE = 0x0219; private const int DBT_DEVICEARRIVAL = 0x8000; private const int DBT_DEVTYP_DEVICEINTERFACE = 0x00000005; private const uint DEVICE_NOTIFY_SERVICE_HANDLE = 0x00000001; [StructLayout(LayoutKind.Sequential)] private struct DEV_BROADCAST_HDR { public int dbch_size; public int dbch_devicetype; public int dbch_reserved; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] private struct DEV_BROADCAST_DEVICEINTERFACE { public int dbcc_size; public int dbcc_devicetype; public int dbcc_reserved; public Guid dbcc_classguid; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string dbcc_name; } protected override void OnStart(string[] args) { // 注册USB设备类通知 var dbi = new DEV_BROADCAST_DEVICEINTERFACE(); dbi.dbcc_size = Marshal.SizeOf(dbi); dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; dbi.dbcc_classguid = Guid.Parse("{A5DCBF10-6530-11D2-901F-00C04FB951ED}"); // USB设备类GUID var buffer = Marshal.AllocHGlobal(dbi.dbcc_size); Marshal.StructureToPtr(dbi, buffer, true); _notificationHandle = RegisterDeviceNotification(this.ServiceHandle, buffer, DEVICE_NOTIFY_SERVICE_HANDLE); } protected override void WndProc(ref Message m) { if (m.Msg == WM_DEVICECHANGE) { if ((int)m.WParam == DBT_DEVICEARRIVAL) { var hdr = (DEV_BROADCAST_HDR)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_HDR)); if (hdr.dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) { var dbi = (DEV_BROADCAST_DEVICEINTERFACE)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_DEVICEINTERFACE)); // 此处添加设备属性处理逻辑,如读取注册表信息、设备路径等 WriteLog($"新USB设备连接: {dbi.dbcc_name}"); } } } base.WndProc(ref m); } protected override void OnStop() { if (_notificationHandle != IntPtr.Zero) { UnregisterDeviceNotification(_notificationHandle); } } private void WriteLog(string message) { // 实现日志写入逻辑,如写入事件查看器或文件 EventLog.WriteEntry("USBDeviceMonitor", message, EventLogEntryType.Information); } }
部署说明
- 将代码编译为Windows服务,使用
installutil.exe安装并设置为自动启动 - 服务需以管理员权限运行,确保能访问硬件设备信息
内容的提问来源于stack exchange,提问作者Tristan Schlarman
相关产品推荐
相关产品推荐

