【问题标题】:Detect external devices insertion on Windows在 Windows 上检测外部设备插入
【发布时间】:2016-12-08 23:45:49
【问题描述】:

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

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

  1. 使用 WMI,如 here。但我实际上无法理解 WMI 在哪里。
  2. 使用 RegisterDeviceNotification 和 WM_DEVICECHANGE。据我所知,控制台应用程序无法做到这一点,只能使用 GUI(真实窗口)或仅消息窗口进行一次。我已经用this answer 的示例尝试了最后一个,但是当我插入我的 USB 闪存驱动器时,我的应用程序没有收到任何通知。我找到了this answer(来自与上述答案相同的问题)并尝试使用 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 函数,如this answer。但是这种方式似乎不是我的问题的完美解决方案。

我的问题是

  1. 谁能解释一下最好的方法是什么?如果它是 RegisterDeviceNotification 的第二个,为什么它在仅消息窗口应用程序的情况下不起作用?
  2. 是否存在其他方法?如果没有,我该怎么做,例如,在安装某些特定软件时通知应用程序?

感谢任何 cmets。

【问题讨论】:

  • 仅消息窗口是 Win32 中的常见模式。控制台应用程序创建仅消息窗口应该没有问题,但如果您的主线程不是事件驱动的,您可能希望在不同的线程上执行此操作。
  • 当你说“我用这个答案的例子尝试了最后一个”时,你的意思是你编译并运行了这个例子,没有任何改变,对吧?
  • @immibis 是的,我是这个意思。所以我应该为仅消息窗口创建新线程?
  • @heyjohnnyfunt:问题的核心是你必须重复call GetMessage and DispatchMessage。正如 immibis 试图解释的那样,您可以从您的主线程执行此操作,或者如果更方便,可以从另一个线程执行此操作。 (我强烈建议也从同一个线程调用CreateWindowEx
  • @MSalters:但我正在努力按照你说的去做。我在您提供的 MSDN 上使用 GetMessage 的示例进行了 while 循环,并且还使用了 CreateWindowEx,但我在控制台中看不到任何消息。这意味着我的应用没有收到WM_DEVICECHANGE 事件。我也试过在另一个线程中这样做,但结果是一样的。

标签: c++ windows winapi events usb


【解决方案1】:

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

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

    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. 至于应用程序可以注册的其他类型的windows通知,我只找到了一个partially deprecated list of all Win32 API functions,在那里我发现了一些新的使用Ctrl+F搜索的通知:)

希望这可以节省一些人的时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-15
    • 1970-01-01
    • 1970-01-01
    • 2014-03-22
    • 2011-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多