检测Windows上的外部设备插入

Detect external devices insertion on Windows

本文关键字:外部设备 插入 Windows 检测      更新时间:2023-10-16

我有点困惑于如何用用户插入设备(USB、HID等)的事件通知我的c++应用程序。应用程序类型没有定义。我试着玩控制台/仅消息/服务示例应用程序,但没有结果。我使用的是VS2015和Windows 10。

我发现有多种方法来处理它:

  1. 像这里一样使用WMI。但我真的不明白WMI在哪里
  2. 使用RegisterDeviceNotification和WM_DEVICECHANGE。据我所知,控制台应用程序没有办法做到这一点,只有一次使用GUI(真实窗口)或仅消息窗口。我已经用这个答案中的例子尝试了最后一个,但当我插入U盘时,我的应用程序不会收到任何通知。我找到了这个答案(来自与上面提到的答案相同的问题),并尝试使用ChangeWindowMessageFilterEx()函数和来自user32.dll的GetProcAddress来加载它,而不需要将dll连接到我的应用程序,方法如下:

    BOOL InitInstance(HWND hWnd)
    {            
        HMODULE hDll = GetModuleHandle(TEXT("user32.dll"));
        if (hDll)
        {   
            typedef BOOL(WINAPI *MESSAGEFILTERFUNCEX)(HWND hWnd, UINT message, DWORD action, VOID* pChangeFilterStruct);
            const DWORD MSGFLT_ALLOW = 1;
            MESSAGEFILTERFUNCEX ChangeWindowMessageFilterEx= (MESSAGEFILTERFUNCEX)::GetProcAddress(hDll, "ChangeWindowMessageFilterEx");
            if (ChangeWindowMessageFilterEx) return func(hWnd, WM_COPYDATA, MSGFLT_ALLOW, NULL);
        }
        return FALSE;    }
    

    这个功能的用途是:

        hWnd = CreateWindowEx(0, CLS_NAME, "DevNotifWnd", WS_ICONIC,
            0, 0, CW_USEDEFAULT, 0, HWND_MESSAGE,
            NULL, GetModuleHandle(0), (void*)&guid);
        InitInstance(hWnd);
    

    但没有效果。

  3. 使用while(true){...}循环并调用适当的Win API函数,如本答案所示。但这种方式似乎不是解决我问题的完美方法。

我的问题是

  1. 有人能告诉我什么是最好的方法吗?如果它是第二个带有RegisterDeviceNotification的应用程序,为什么它在仅消息窗口应用程序的情况下不起作用
  2. 是否存在其他方式?若并没有,我能做些什么,例如,当安装了某些软件时通知应用程序

欢迎发表任何意见。

所以我终于找到了问题的答案。

  1. 问题出在我为NotificationFilter提供的GUID上。因此,我使用以下代码将其设置为接收来自所有设备的通知:DEV_BROADCAST_DEVICEINTERFACE通知过滤器;

    ZeroMemory(&NotificationFilter,sizeof(NotificationFilter));

    NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
    NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    // No need to set up dbcc_classguid as it is ignored when 
    // DEVICE_NOTIFY_ALL_INTERFACE_CLASSES is setted (see line down below)
    HDEVNOTIFY dev_notify = RegisterDeviceNotification(hwnd, &NotificationFilter, DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
    
  2. 至于应用程序可以注册的窗口中的其他类型的通知,我只找到了一个部分不推荐使用的所有Win32 API函数列表,在那里我找到了一些使用Ctrl+F搜索的新通知:)

希望这能节省一些时间。