События устройства Win32: Не получено DBT_DEVTYP_VOLUME в событии DBT_DEVICEARRIVAL - PullRequest
0 голосов
/ 14 октября 2019

То, что я в основном пытаюсь сделать, - это создание службы Windows, которая прослушивает вставку запоминающего устройства, например (флэш-накопитель USB, внешний жесткий диск / твердотельный накопитель) ... Я выполняю следующие 2 урока:


У меня правильно работает сервисная часть, я также получаю уведомления об устройстве.
Но когда я пытаюсь установить флэш-накопитель USB, я получаю уведомление, но dbch_devicetype в PDEV_BROADCAST_HDR всегда DBT_DEVTYP_DEVICEINTERFACE никогда DBT_DEVTYP_VOLUME. Также, когда я RegisterDeviceNotification с DBT_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);
            }
        }
    }
    }
}

1 Ответ

1 голос
/ 14 октября 2019

сначала ваш неправильный регистр для объемного уведомления. код должен быть

        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_DEVINTERFACE_VOLUME, если вы хотите уведомление о прибытии / удалении тома, но не GUID_DEVCLASS_VOLUME (вы используете его как { 0x71a27cdd, 0x812a, 0x11d0, 0xbe, 0xc7, 0x08, 0x00, 0x2b, 0xe2, 0x09, 0x2f };). с GUID_DEVCLASS_VOLUME вы никогда не получали уведомлений, потому что это не guid интерфейса. Вы получили уведомления только потому, что установите флаг set DEVICE_NOTIFY_ALL_INTERFACE_CLASSES - уведомляет получателя о событиях интерфейса устройства для всех классов интерфейса устройства. (Член dbcc_classguid игнорируется .)

, тогда в обработчике - вы должны получить dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE тип уведомления (не DBT_DEVTYP_VOLUME) также будет dbcc_classguid == GUID_DEVINTERFACE_VOLUME, если вы зарегистрируетесь точно дляGUID_DEVINTERFACE_VOLUME только. так что вы можете привести lpEventData к PDEV_BROADCAST_DEVICEINTERFACE и использовать dbcc_name member - это символическая ссылка win32 на имя тома (может использоваться в вызове CreateFileW)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...