【问题标题】:Win32 Device Events : Not receiving DBT_DEVTYP_VOLUME on DBT_DEVICEARRIVAL eventWin32 设备事件:在 DBT_DEVICEARRIVAL 事件上未收到 DBT_DEVTYP_VOLUME
【发布时间】:2019-10-13 22:11:24
【问题描述】:

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


我的服务部分运行正常,我也收到了设备通知。
但是当我尝试放入 USB 闪存驱动器时,我收到了一个通知,但 dbch_devicetypePDEV_BROADCAST_HDRis总是DBT_DEVTYP_DEVICEINTERFACE 从不DBT_DEVTYP_VOLUME。此外,当我 RegisterDeviceNotificationDBT_DEVTYP_VOLUME 时,我什么也没有收到。我已经搜索了几个小时,但找不到为什么我没有收到正确的通知

负责为设备通知注册服务的功能:
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);
            }
        }
    }
    }
}

【问题讨论】:

  • 你必须得到dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE,因为你注册了NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;,你需要使用NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_VOLUME而不是GUID_DEVCLASS_VOLUME
  • @RbMm 我尝试使用 GUID_DEVINTERFACE_VOLUME 但它不起作用(我收到了闪存驱动器的通知,但它也将鼠标注册为存储设备)
  • 因为你的代码错误太多
  • @RbMm 没有代码编译正常
  • 这里的代码编译方式有什么关系?

标签: c++ winapi windows-services


【解决方案1】:

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

        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(您将其用作{ 0x71a27cdd, 0x812a, 0x11d0, 0xbe, 0xc7, 0x08, 0x00, 0x2b, 0xe2, 0x09, 0x2f };),则需要使用GUID_DEVINTERFACE_VOLUME。使用GUID_DEVCLASS_VOLUME,您永远不会收到通知,因为这不是界面 guid。您收到通知只是因为使用 set DEVICE_NOTIFY_ALL_INTERFACE_CLASSES 标志 - 通知所有设备接口类的设备接口事件的接收者。 (dbcc_classguid 成员被忽略。)

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

【讨论】:

  • 你能给我一个使用dbcc_name打开驱动器的例子吗?
  • @MekacherAnis - 我怎么说 - 只需将其传递给调用 CreateFileW 作为第一个参数
猜你喜欢
  • 1970-01-01
  • 2017-05-18
  • 1970-01-01
  • 2019-09-11
  • 2014-02-07
  • 2019-08-18
  • 2017-10-15
  • 1970-01-01
  • 2019-12-22
相关资源
最近更新 更多