c++ - Win32 设备事件 : Not receiving DBT_DEVTYP_VOLUME on DBT_DEVICEARRIVAL event

标签 c++ winapi windows-services

我基本上想做的是制作一个 Windows 服务来监听存储设备插入,例如(USB 闪存驱动器、外部 HDD/SSD)... 我正在学习这两个教程:


我的服务部分运行正常,我也收到了设备通知。
但是当我尝试放入 USB 闪存驱动器时,我收到了通知,但是 dbch_devicetypePDEV_BROADCAST_HDR 中始终是 DBT_DEVTYP_DEVICEINTERFACE 而不是 DBT_DEVTYP_VOLUME。此外,当我使用 DBT_DEVTYP_VOLUME RegisterDeviceNotification 时,我没有收到任何东西。我已经搜索了几个小时,但找不到为什么我没有收到正确的通知

负责注册设备通知服务的函数:

void Myclassname::registerForDeviceNotifications() {
    DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
    ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
    NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
    NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    NotificationFilter.dbcc_classguid = { 0x71a27cdd, 0x812a, 0x11d0, 0xbe, 0xc7, 0x08, 0x00, 0x2b, 0xe2, 0x09, 0x2f };

    m_hDevNotify = RegisterDeviceNotification(m_statusHandle,
        &NotificationFilter, DEVICE_NOTIFY_SERVICE_HANDLE |
        DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
}

负责处理设备通知的函数:

void AutobackupService::handleDeviceChangeNotif(DWORD dwEventType, LPVOID lpEventData) {
    switch (dwEventType) {
    case DBT_DEVICEREMOVECOMPLETE: {
        PDEV_BROADCAST_HDR eventData = (PDEV_BROADCAST_HDR)lpEventData;
        logToFile(std::to_string(eventData->dbch_devicetype));
        if (eventData->dbch_devicetype == DBT_DEVTYP_VOLUME)
        {
            PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)eventData;
            if (lpdbv->dbcv_flags & DBTF_MEDIA)
            {
                WriteEventLogEntry(L"USB device removed " + lpdbv->dbcv_unitmask, EVENTLOG_INFORMATION_TYPE);
            }
        }
    }
                                   break;
    case DBT_DEVICEARRIVAL: {
        PDEV_BROADCAST_HDR eventData = (PDEV_BROADCAST_HDR)lpEventData;
        logToFile(std::to_string(eventData->dbch_devicetype));
        if (eventData->dbch_devicetype == DBT_DEVTYP_VOLUME)
        {
            PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)eventData;
            if (lpdbv->dbcv_flags & DBTF_MEDIA)
            {
                WriteEventLogEntry(L"USB device removed " + lpdbv->dbcv_unitmask, EVENTLOG_INFORMATION_TYPE);
            }
        }
    }
    }
}

最佳答案

起初你错误地注册了音量通知。代码必须是

        static DEV_BROADCAST_DEVICEINTERFACE NotificationFilter = { 
            sizeof(DEV_BROADCAST_DEVICEINTERFACE), 
            DBT_DEVTYP_DEVICEINTERFACE,
            0,
            GUID_DEVINTERFACE_VOLUME
        };

        m_hDevNotify = RegisterDeviceNotification(m_statusHandle,
             &NotificationFilter, DEVICE_NOTIFY_SERVICE_HANDLE);

请注意,如果您需要体积到达/移除通知而不是GUID_DEVCLASS_VOLUME,则需要使用GUID_DEVINTERFACE_VOLUME(您将其用作{ 0x71a27cdd, 0x812a, 0x11d0, 0xbe, 0xc7、0x08、0x00、0x2b、0xe2、0x09、0x2f};)。使用 GUID_DEVCLASS_VOLUME 你永远不会收到通知,因为这不是接口(interface) guid。您收到通知只是因为使用了 set DEVICE_NOTIFY_ALL_INTERFACE_CLASSES 标志 - 通知所有设备接口(interface)类的设备接口(interface)事件的接收者。 (dbcc_classguid 成员被忽略。)

然后在处理程序中 - 您必须得到 dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE 类型的通知(不是 DBT_DEVTYP_VOLUME)也将是 dbcc_classguid == GUID_DEVINTERFACE_VOLUME 如果您只为 GUID_DEVINTERFACE_VOLUME 注册。因此您可以将 lpEventData 转换为 PDEV_BROADCAST_DEVICEINTERFACE 并使用 dbcc_name 成员 - 这是指向卷名的 win32 符号链接(symbolic link)(可用于调用 创建文件W)

关于c++ - Win32 设备事件 : Not receiving DBT_DEVTYP_VOLUME on DBT_DEVICEARRIVAL event,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58368184/

相关文章:

c# - wmic 通过 .NET 或 C#

c++ - 交换树数据结构中根的 2 个子节点指针

c++ - 如果类的私有(private)成员不能被非成员函数访问,那么为什么 main() 能够在这个程序中打印电话的值呢?

c++ - 为什么使用带有自定义比较器的 std::sort 无法编译?

c++ - 如何开始用 C++ 编写音乐可视化工具?

winapi - FindAllAsync 在 Windows 应用商店应用程序中找不到设备

delphi - 如何仅通过知道其句柄来确定 Canvas 尺寸?

c++ - Windows Api 多线程消息

c# - Windows 服务可以在未登录的情况下启动应用程序吗?

c# - Nancy 的 Windows 服务无法启动主机