检测何时安装驱动器或更改状态(WMF的WM_DEVICECHANGE)?

ako*_*nsu 2 .net wpf

我正在为WPF编写一个目录选择器控件,我想在安装或卸载时或者当它准备好或没有准备好时(例如用户插入或删除CD)从目录树中添加/删除驱动器.我正在寻找类似的系统事件WM_DEVICECHANGE.

康斯坦丁

Zac*_*son 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);
    }
}
Run Code Online (Sandbox Code Playgroud)


sto*_*eur 5

我使用WMI来实现这样的东西(就像Richard在他的回答中所述)

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:我自己没有发明代码,我想我是从这里得到的