我正在为WPF编写一个目录选择器控件,我想在挂载或卸载时或者当它准备好或没有准备好时(例如用户插入或删除CD)从目录树中添加/删除驱动器)。我正在寻找类似于WM_DEVICECHANGE
的系统事件。
康斯坦丁
答案 0 :(得分:5)
即使您使用的是WPF,仍然可以截取WM_DEVICECHANGE
。您可以使用WPF回调方法附加到现有窗口过程,也可以使用System.Windows.Forms.NativeWindow
(我的首选方法,更多控件和更简单,但您需要添加对System.Windows.Forms.dll的引用)
// in your window's code behind
private static int WM_DEVICECHANGE = 0x0219;
protected override void OnSourceInitialized(EventArgs e)
{
WindowInteropHelper helper = new WindowInteropHelper(this);
SystemEventIntercept intercept = new SystemEventIntercept(helper.Handle);
base.OnSourceInitialized(e);
}
class SystemEventIntercept : System.Windows.Forms.NativeWindow
{
public SystemEventIntercept(IntPtr handle)
{
this.AssignHandle(handle);
}
protected override void WndProc(ref Winforms.Message m)
{
if (m.Msg == WM_DEVICECHANGE)
{
// do something
}
base.WndProc(ref m);
}
}
答案 1 :(得分:5)
我使用WMI来实现这样的事情(就像理查德在他的回答中所说的那样)
using System.Management;
using System;
...
private void SubscribeToCDInsertion()
{
WqlEventQuery q;
ManagementOperationObserver observer = new ManagementOperationObserver();
// Bind to local machine
ConnectionOptions opt = new ConnectionOptions();
opt.EnablePrivileges = true; //sets required privilege
ManagementScope scope = new ManagementScope("root\\CIMV2", opt);
q = new WqlEventQuery();
q.EventClassName = "__InstanceModificationEvent";
q.WithinInterval = new TimeSpan(0, 0, 1);
// DriveType - 5: CDROM
q.Condition = @"TargetInstance ISA 'Win32_LogicalDisk' and TargetInstance.DriveType = 5";
var w = new ManagementEventWatcher(scope, q);
try
{
// register async. event handler
w.EventArrived += new EventArrivedEventHandler(driveInsertEvent);
w.Start();
}
catch (Exception e)
{
w.Stop();
}
}
void driveInsertEvent(object sender, EventArrivedEventArgs e)
{
// Get the Event object and display it
PropertyData pd = e.NewEvent.Properties["TargetInstance"];
if (pd != null)
{
ManagementBaseObject mbo = pd.Value as ManagementBaseObject;
// if CD removed VolumeName == null
if (mbo.Properties["VolumeName"].Value != null)
{
//do something
}
}
}
编辑:我自己没有发明代码,我想我是从here
得到的答案 2 :(得分:2)
以下代码对我有用。它订阅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);
}
}
}
}
答案 3 :(得分:1)
你可以:
WinProc
方法来获取WM_DEVICECHANGE
。