.net 检测驱动器何时安装或更改状态(WPF的WM_设备更改)?
我正在为WPF编写一个目录选择器控件,我想在安装或卸载驱动器时,或者在驱动器准备就绪或未准备就绪时(例如,用户插入或删除CD),从目录树中添加/删除驱动器。我正在寻找类似于.net 检测驱动器何时安装或更改状态(WPF的WM_设备更改)?,.net,wpf,.net,Wpf,我正在为WPF编写一个目录选择器控件,我想在安装或卸载驱动器时,或者在驱动器准备就绪或未准备就绪时(例如,用户插入或删除CD),从目录树中添加/删除驱动器。我正在寻找类似于WM\u DEVICECHANGE的系统事件 康斯坦丁你可以: using System; using System.Management; namespace consapp { class Program { static void Main(string[] args)
WM\u DEVICECHANGE
的系统事件
康斯坦丁你可以:
using System;
using System.Management;
namespace consapp
{
class Program
{
static void Main(string[] args)
{
const string QUERY = @"select * from __InstanceOperationEvent within 1 where TargetInstance isa 'Win32_LogicalDisk' and (TargetInstance.DriveType=2 or TargetInstance.DriveType=5)";
Program p = new Program();
ManagementEventWatcher w = new ManagementEventWatcher(new WqlEventQuery(QUERY));
w.EventArrived += new EventArrivedEventHandler(p.OnWMIEvent);
w.Start();
Console.ReadKey();
w.Stop();
}
public void OnWMIEvent(object sender, EventArrivedEventArgs e)
{
PropertyData p = e.NewEvent.Properties["TargetInstance"];
if (p != null)
{
ManagementBaseObject mbo = p.Value as ManagementBaseObject;
PropertyData deviceid = mbo.Properties["DeviceID"];
PropertyData drivetype = mbo.Properties["DriveType"];
Console.WriteLine("{0}-{1}:{2}", deviceid.Value, drivetype.Value, e.NewEvent.ClassPath);
}
}
}
}
- 使用WMI和WMI事件检测硬件更改
- 使用隐藏的WinForms窗口,覆盖要拾取的方法
WM\u设备更改
。您可以使用WPF回调方法附加到现有的窗口过程,也可以使用System.Windows.Forms.NativeWindow
(我的首选方法,更易于控制,但您确实需要添加对System.Windows.Forms.dll的引用)
我使用WMI实现了类似的东西(如Richard在回答中所述)
编辑:代码不是我自己发明的,我想我是从下面的代码中得到的。它订阅DriveType=2和DriveType=5事件以检测cd-rom和usb。因为我不需要知道驱动器是否已安装或卸载,或者cd是否已卸下或插入,所以代码不会检查这一点。对于usb挂载,可以使用e.NewEvent.ClassPath来判断驱动器是否已连接或断开连接 另外,我在互联网上发现了一些令人困惑的评论,说订阅DriveType=5的事件也会检测usb挂载。这对我不起作用 康斯坦丁
using System;
using System.Management;
namespace consapp
{
class Program
{
static void Main(string[] args)
{
const string QUERY = @"select * from __InstanceOperationEvent within 1 where TargetInstance isa 'Win32_LogicalDisk' and (TargetInstance.DriveType=2 or TargetInstance.DriveType=5)";
Program p = new Program();
ManagementEventWatcher w = new ManagementEventWatcher(new WqlEventQuery(QUERY));
w.EventArrived += new EventArrivedEventHandler(p.OnWMIEvent);
w.Start();
Console.ReadKey();
w.Stop();
}
public void OnWMIEvent(object sender, EventArrivedEventArgs e)
{
PropertyData p = e.NewEvent.Properties["TargetInstance"];
if (p != null)
{
ManagementBaseObject mbo = p.Value as ManagementBaseObject;
PropertyData deviceid = mbo.Properties["DeviceID"];
PropertyData drivetype = mbo.Properties["DriveType"];
Console.WriteLine("{0}-{1}:{2}", deviceid.Value, drivetype.Value, e.NewEvent.ClassPath);
}
}
}
}
谢谢我怀疑这是不可移植的,它不会在其他操作系统上工作。你能解释一下在OnSourceInitialized方法中创建SystemEventIntercept对象而不在任何地方使用它的目的吗?@akonsu:是的,这个解决方案不可移植,但我认为WPF也不可移植<代码>OnSourceInitialized在创建WPF窗口的底层Win32句柄时被调用,因此它是一个方便的连接到它的地方。
SystemEventIntercept
实际上正在做一些事情,当它被创建时,它立即开始侦听消息。当您截取WM_DEVICECHANGE
时,您可以在//do something
注释中执行任何需要的操作。我的代码只是一个例子,您可能需要修改它以满足您的需要。+1:这正是我检测专用USB设备所需的,因为接受答案将只检测存储设备。起初,直到我将SystemEventIntercept
作为一个属性而不是一个局部变量,这个解决方案才起作用,然后它工作得很好。作为一个局部变量(从未使用过),它必须几乎立即被垃圾收集。
using System;
using System.Management;
namespace consapp
{
class Program
{
static void Main(string[] args)
{
const string QUERY = @"select * from __InstanceOperationEvent within 1 where TargetInstance isa 'Win32_LogicalDisk' and (TargetInstance.DriveType=2 or TargetInstance.DriveType=5)";
Program p = new Program();
ManagementEventWatcher w = new ManagementEventWatcher(new WqlEventQuery(QUERY));
w.EventArrived += new EventArrivedEventHandler(p.OnWMIEvent);
w.Start();
Console.ReadKey();
w.Stop();
}
public void OnWMIEvent(object sender, EventArrivedEventArgs e)
{
PropertyData p = e.NewEvent.Properties["TargetInstance"];
if (p != null)
{
ManagementBaseObject mbo = p.Value as ManagementBaseObject;
PropertyData deviceid = mbo.Properties["DeviceID"];
PropertyData drivetype = mbo.Properties["DriveType"];
Console.WriteLine("{0}-{1}:{2}", deviceid.Value, drivetype.Value, e.NewEvent.ClassPath);
}
}
}
}