捕获USB插件并拔出事件System.InvalidCastException

我正在尝试检测USB设备插入并使用WinForm桌面C#应用程序删除:

public Form1() { InitializeComponent(); USB(); } 

然后:

 private void USB() { WqlEventQuery weqQuery = new WqlEventQuery(); weqQuery.EventClassName = "__InstanceOperationEvent"; weqQuery.WithinInterval = new TimeSpan(0, 0, 3); weqQuery.Condition = @"TargetInstance ISA 'Win32_DiskDrive'"; var m_mewWatcher = new ManagementEventWatcher(weqQuery); m_mewWatcher.EventArrived += new EventArrivedEventHandler(m_mewWatcher_EventArrived); m_mewWatcher.Start(); } 

和:

 static void m_mewWatcher_EventArrived(object sender, EventArrivedEventArgs e) { bool bUSBEvent = false; foreach (PropertyData pdData in e.NewEvent.Properties) { ManagementBaseObject mbo = (ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value; // ManagementBaseObject mbo = (ManagementBaseObject)pdData.Value; if (mbo != null) { foreach (PropertyData pdDataSub in mbo.Properties) { if (pdDataSub.Name == "InterfaceType" && pdDataSub.Value.ToString() == "USB") { bUSBEvent = true; break; } } if (bUSBEvent) { if (e.NewEvent.ClassPath.ClassName == "__InstanceCreationEvent") { MessageBox.Show ("USB was plugged in"); } else if (e.NewEvent.ClassPath.ClassName == "__InstanceDeletionEvent") { MessageBox.Show("USB was plugged out"); } } } } } 

但我在ManagementBaseObject mbo = (ManagementBaseObject)pdData.Value;遇到exceptionManagementBaseObject mbo = (ManagementBaseObject)pdData.Value; 检测到USB更改时:

Controller.exe中出现“System.InvalidCastException”类型的exception,但未在用户代码中处理

附加信息:无法将类型为“System.UInt64”的对象强制转换为“System.Management.ManagementBaseObject”。

编辑:

 using System; using System.Windows.Forms; using System.Management; namespace test { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { WqlEventQuery query = new WqlEventQuery() { EventClassName = "__InstanceOperationEvent", WithinInterval = new TimeSpan(0, 0, 3), Condition = @"TargetInstance ISA 'Win32_DiskDrive'" }; using (ManagementEventWatcher MOWatcher = new ManagementEventWatcher(query)) { MOWatcher.EventArrived += new EventArrivedEventHandler(DeviceInsertedEvent); MOWatcher.Start(); } } private void DeviceInsertedEvent(object sender, EventArrivedEventArgs e) { using (ManagementBaseObject MOBbase = (ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value) { bool DriveArrival = false; string EventMessage = string.Empty; string oInterfaceType = MOBbase.Properties["InterfaceType"]?.Value.ToString(); if (e.NewEvent.ClassPath.ClassName.Equals("__InstanceDeletionEvent")) { DriveArrival = false; EventMessage = oInterfaceType + " Drive removed"; } else { DriveArrival = true; EventMessage = oInterfaceType + " Drive inserted"; } EventMessage += ": " + MOBbase.Properties["Caption"]?.Value.ToString(); this.BeginInvoke((MethodInvoker)delegate { this.UpdateUI(DriveArrival, EventMessage); }); } } private void UpdateUI(bool IsDriveInserted, string message) { if (IsDriveInserted) { this.label1.Text = message; } else { this.label1.Text = message; } } } } 

这里, ManagementEventWatcher在Button.Click()事件上初始化。 当然,您可以在其他地方初始化它。 例如,在Form.Load()中。

订阅ManagementEventWatcher.EventArrived事件,将委托设置为private void DeviceInsertedEvent() 。 观察过程是使用ManagementEventWatcher.Start()开始的( MOWatcher.Start();

通知事件时, EventArrivedEventArgs e.NewEvent 。 Properties["TargetInstance"].Value将设置为ManagementBaseObject ,它将引用Win32_DiskDrive WMI / CIM类。
阅读文档以查看此类中可用的信息。

UI线程中没有出现此事件。 要通知主UI界面事件的性质,我们需要.Invoke()该线程中的方法。

this.BeginInvoke((MethodInvoker)delegate { this.UpdateUI(DriveArrival, EventMessage); });

这里,调用private void UpdateUI()方法,将UI更新委托给在UI线程中执行的方法。

更新:
添加RegisterWindowMessage()来注册QueryCancelAutoPlay ,以防止AutoPlay窗口弹出我们的Form前面,窃取焦点。

结果的可视化样本:

WMI_EventWatcher

 [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] internal static extern uint RegisterWindowMessage(string lpString); private uint CancelAutoPlay = 0; private void button1_Click(object sender, EventArgs e) { WqlEventQuery query = new WqlEventQuery() { EventClassName = "__InstanceOperationEvent", WithinInterval = new TimeSpan(0, 0, 3), Condition = @"TargetInstance ISA 'Win32_DiskDrive'" }; ManagementScope scope = new ManagementScope("root\\CIMV2"); using (ManagementEventWatcher MOWatcher = new ManagementEventWatcher(query)) { MOWatcher.Options.Timeout = ManagementOptions.InfiniteTimeout; MOWatcher.EventArrived += new EventArrivedEventHandler(DeviceInsertedEvent); MOWatcher.Start(); } } private void DeviceInsertedEvent(object sender, EventArrivedEventArgs e) { using (ManagementBaseObject MOBbase = (ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value) { bool DriveArrival = false; string EventMessage = string.Empty; string oInterfaceType = MOBbase.Properties["InterfaceType"]?.Value.ToString(); if (e.NewEvent.ClassPath.ClassName.Equals("__InstanceDeletionEvent")) { DriveArrival = false; EventMessage = oInterfaceType + " Drive removed"; } else { DriveArrival = true; EventMessage = oInterfaceType + " Drive inserted"; } EventMessage += ": " + MOBbase.Properties["Caption"]?.Value.ToString(); this.BeginInvoke((MethodInvoker)delegate { this.UpdateUI(DriveArrival, EventMessage); }); } } private void UpdateUI(bool IsDriveInserted, string message) { if (IsDriveInserted) this.lblDeviceArrived.Text = message; else this.lblDeviceRemoved.Text = message; } [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] protected override void WndProc(ref Message m) { base.WndProc(ref m); if (CancelAutoPlay == 0) CancelAutoPlay = RegisterWindowMessage("QueryCancelAutoPlay"); if ((int)m.Msg == CancelAutoPlay) { m.Result = (IntPtr)1; } }