c#usb检测

use*_*293 5 .net c# usb

我们在当前的应用程序中有几个进程.一个过程处理USB加载程序的检测和删除.处理检测和删除的代码如下.

protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case Win32.WM_DEVICECHANGE: OnDeviceChange(ref m);
                    break;
            }
            base.WndProc(ref m);
        }

private void OnDeviceChange(ref Message msg)
        {
            int wParam = (int)msg.WParam;
            Win32.DEV_BROADCAST_VOLUME dbVol = new Win32.DEV_BROADCAST_VOLUME();
            Win32.DEV_BROADCAST_HDR msgDevHeader = new Win32.DEV_BROADCAST_HDR();
            const int DBT_DEVTYP_VOLUME = 0x00000002;
            string loaderUpdates;

            switch (wParam)
            {
                case Win32.DBT_DEVICEARRIVAL:
                    int devType = Marshal.ReadInt32(msg.LParam, 4);

                    if (devType == DBT_DEVTYP_VOLUME)
                    {
                    }
                    break;

                case Win32.DBT_DEVICEREMOVECOMPLETE:

                                     break;
            }
        }
Run Code Online (Sandbox Code Playgroud)

当我在visual studio环境中运行以调试模式处理USB加载程序的过程时,它会正确检测USB.但我仍然会收到多条消息.接收wparam值为"7"3次的消息,然后接收wparam值为"32768(0x8000/DBT_DEVICEARRIVAL)".这是正常的吗?

当我运行所有其他进程以及检测USB的进程时,似乎始终是仅接收到wparam值为"7"的消息.用wparam作为"7"5次接收meesage.没有wparam值为"(0x8000/DBT_DEVICEARRIVAL)"的消息.可能是什么问题呢?

感谢任何输入/解决方案.

问候Raju

dot*_*emy 3

据我所见,这是正常的。我在这里遇到了完全相同的问题。

您可以做两件事 - 为 DateTime.Now 设置一个 var,然后检查下一个到达时间,看看到达时间之间的时间差是否距上次发生事件的时间小于 x 秒(基本上存储您上次到达的时间)处理到达)

或者

您可以存储驱动器列表,如果事件处理与您已有的设备相同的设备,则可以忽略它。

但是,是的,因为 USB 设备通常将自己作为多个设备呈现给系统,所以它往往会发送多个设备插入。

我用来解决这个问题的另一件事是使用 WMI 的事件,通过观察程序来检测逻辑存储事件(__InstanceCreation ,目标为 Win32_LogicalDisk)

    private void startMonitor()
    {
        while (serviceStarted)
        {
            ManagementEventWatcher watcher = new ManagementEventWatcher();

            WqlEventQuery query = new WqlEventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_LogicalDisk'");

            watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
            watcher.Query = query;
            watcher.Start();
            watcher.WaitForNextEvent();
        }
        Thread.CurrentThread.Abort();
    }
Run Code Online (Sandbox Code Playgroud)

使用 EventArrived 处理程序...

    private void watcher_EventArrived(object obj, EventArrivedEventArgs e)
    {
            var newEvent = e.NewEvent;

            ManagementBaseObject targetInstance = (ManagementBaseObject)newEvent.GetPropertyValue("TargetInstance");

            string drivename = targetInstance.GetPropertyValue("Name").ToString();
Run Code Online (Sandbox Code Playgroud)

Drivename 最终实际上是驱动器号,例如 D: 或其他......

缺点是应用程序需要以本地 WMI 范围的正确权限运行,并且比被动处理窗口消息稍微密集一些。