Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 检测驱动器何时安装或更改状态(WPF的WM_设备更改)?_.net_Wpf - Fatal编程技术网

.net 检测驱动器何时安装或更改状态(WPF的WM_设备更改)?

.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)

我正在为WPF编写一个目录选择器控件,我想在安装或卸载驱动器时,或者在驱动器准备就绪或未准备就绪时(例如,用户插入或删除CD),从目录树中添加/删除驱动器。我正在寻找类似于
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窗口,覆盖要拾取的方法

即使您正在使用WPF,您仍然可以拦截
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);
            }
        }
    }
}