Win32 设备事件:在 DBT_DEVICEARRIVAL 事件上未收到 DBT_DEVTYP_VOLUME
Win32 Device Events : Not receiving DBT_DEVTYP_VOLUME on DBT_DEVICEARRIVAL event
我基本上想做的是制作一个 windows 服务来侦听存储设备插入,例如(USB 闪存驱动器,外部 HDD/SSD)...
我正在学习这两个教程:
- https://www.codeproject.com/Articles/15612/Receiving-Device-Event-Notification-in-Windows-Ser
- https://docs.microsoft.com/en-us/windows/win32/devio/detecting-media-insertion-or-removal
我得到了服务部分 运行 正确,我也收到了设备通知。
但是 当我尝试放入 USB 闪存驱动器时,我收到通知但是 PDEV_BROADCAST_HDR
中的 dbch_devicetype
总是 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);
}
}
}
}
}
起初你错误地注册了音量通知。代码必须是
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);
请注意,如果您想要音量 arrival/removal 通知而不是 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 成员被 忽略 。)
然后在处理程序中 - 您必须得到 dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE
类型的通知(不是 DBT_DEVTYP_VOLUME
),如果您只为 GUID_DEVINTERFACE_VOLUME
注册,则也将是 dbcc_classguid == GUID_DEVINTERFACE_VOLUME
。所以你可以将 lpEventData
转换为 PDEV_BROADCAST_DEVICEINTERFACE
并使用 dbcc_name
成员 - 这是 win32 符号 link 到卷名(可用于调用 CreateFileW
)
我基本上想做的是制作一个 windows 服务来侦听存储设备插入,例如(USB 闪存驱动器,外部 HDD/SSD)... 我正在学习这两个教程:
- https://www.codeproject.com/Articles/15612/Receiving-Device-Event-Notification-in-Windows-Ser
- https://docs.microsoft.com/en-us/windows/win32/devio/detecting-media-insertion-or-removal
我得到了服务部分 运行 正确,我也收到了设备通知。
但是 当我尝试放入 USB 闪存驱动器时,我收到通知但是
PDEV_BROADCAST_HDR
中的 dbch_devicetype
总是 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);
}
}
}
}
}
起初你错误地注册了音量通知。代码必须是
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);
请注意,如果您想要音量 arrival/removal 通知而不是 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 成员被 忽略 。)
然后在处理程序中 - 您必须得到 dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE
类型的通知(不是 DBT_DEVTYP_VOLUME
),如果您只为 GUID_DEVINTERFACE_VOLUME
注册,则也将是 dbcc_classguid == GUID_DEVINTERFACE_VOLUME
。所以你可以将 lpEventData
转换为 PDEV_BROADCAST_DEVICEINTERFACE
并使用 dbcc_name
成员 - 这是 win32 符号 link 到卷名(可用于调用 CreateFileW
)