Обнаружение событий вставки / удаления USB в Windows с использованием C ++
-
28-09-2019 - |
Вопрос
Я пишу расширение для существующего приложения, которое необходимо обрабатывать USB-вставка / события удаления. Я знаю VID / PID устройства, представляющего интерес. Однако у меня нет доступа к рукоятке окна, поэтому я не знаю, если RegisterDeviceNotification
будет многое использовать, если не есть способ получить ручку через WINAPI
. Отказ Что было бы лучшим способом обнаружения мероприятий USB вставки / удаления с C ++?
Этот пример код на веб-сайте Microsoft Показывает, как получить уведомления о событиях через WMI:
Как можно было модифицировать для получения событий вставки / удаления USB? Или есть еще один способ, которым я должен идти по этому поводу? Я использую Visual Studio 2008. Спасибо.
ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ
Это то, что я имею до сих пор (минус ошибки):
DEFINE_GUID(GUID_INTERFACE_CP210x, 0x993f7832, 0x6e2d, 0x4a0f, 0xb2, 0x72, 0xe2, 0xc7, 0x8e, 0x74, 0xf9, 0x3e);
MyClass::MyClass()
{
// Generate message-only window
_pWndClassEx = (WNDCLASSEX *)malloc( sizeof(WNDCLASSEX) );
memset( _pWndClassEx, 0, sizeof(WNDCLASSEX) );
_pWndClassEx->cbSize = sizeof(WNDCLASSEX);
_pWndClassEx->lpfnWndProc = (WNDPROC)WndProc; // function which will handle messages
_pWndClassEx->hInstance = GetCurrentModule();
_pWndClassEx->lpszClassName = pClassName;
atom = RegisterClassEx( _pWndClassEx );
_hWnd = CreateWindowEx( 0, pClassName, pWindowName, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL );
// Register the USB device for notification
_pDevIF = (DEV_BROADCAST_DEVICEINTERFACE *)malloc( sizeof(DEV_BROADCAST_DEVICEINTERFACE) );
memset( _pDevIF, 0, sizeof(DEV_BROADCAST_DEVICEINTERFACE) );
_pDevIF->dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
_pDevIF->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
_pDevIF->dbcc_classguid = GUID_INTERFACE_CP210x;
_hNotifyDevNode = RegisterDeviceNotification( _hWnd, _pDevIF, DEVICE_NOTIFY_WINDOW_HANDLE );
}
static bool OnDeviceChange(UINT nEventType, DWORD dwData)
{
switch ( nEventType )
{
case DBT_DEVICEARRIVAL:
// A device has been inserted adn is now available.
break;
case DBT_DEVICEREMOVECOMPLETE:
// Device has been removed.
break;
default:
break;
}
return true;
}
static LRESULT WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch ( message )
{
case WM_DEVICECHANGE:
OnDeviceChange( wParam, lParam ); // Set breakpoint (never gets here)
break;
default:
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
ПК попадает в WndProc
, но не при удавании / вставьте мое USB-устройство. Компьютер никогда не попадает в OnDeviceChange
. Отказ Любые советы будут оценены. Мне нужно обрабатывать неожиданные вставки / снимки USB-устройства. Если это имеет значение, USB-устройство отображается как виртуальный COM-порт для Windows. Спасибо.
Adital Info: Призыв CreateWindowEx
используя класс atom
возвращено RegisterClassEx
Не удается с сообщением об ошибке «Не удается найти класс Window».
_hWnd = CreateWindowEx( 0, (LPCTSTR)&atom, pWindowName, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL );
НОВЫЙ ПОДХОД
Я также пробую этот новый подход. Я пытаюсь записать окно только сообщение, чтобы получить уведомления об изменении устройств для USB-устройства. Я использую MFC, C ++ и Visual Studio 2008. Все компилирует, и он работает без сбоев или блокировки, но обработчик событий никогда не срабатывает. Устройство интереса устанавливается на Windows в качестве виртуального COM-порта.
Мои основные приложения инстанцирует класс, описанный ниже, затем ожидает входного входа символа из опроса клавиатуры с использованием цикла Wide. В течение этого времени ожидания, когда я удаляю, и вставьте мое USB-устройство, ожидая событие для уволи.
class CMessageOnlyWindow : public CWnd
{
DECLARE_DYNAMIC(CMessageOnlyWindow)
private:
DEV_BROADCAST_DEVICEINTERFACE * _pDevIF; // The notification filter.
HDEVNOTIFY _hNotifyDev; // The device notification handle.
public:
CMessageOnlyWindow();
virtual ~CMessageOnlyWindow();
protected:
afx_msg BOOL OnDeviceChange( UINT nEventType, DWORD dwData );
private:
void RegisterNotification( void );
void UnregisterNotification( void );
protected:
DECLARE_MESSAGE_MAP() // Must be last.
};
Для простоты я удалил всю очистку и обработку ошибок:
DEFINE_GUID(GUID_INTERFACE_CP210x, 0x993f7832, 0x6e2d, 0x4a0f, \
0xb2, 0x72, 0xe2, 0xc7, 0x8e, 0x74, 0xf9, 0x3e);
IMPLEMENT_DYNAMIC(CMessageOnlyWindow, CWnd)
CMessageOnlyWindow::CMessageOnlyWindow()
{
CString cstrWndClassName = ::AfxRegisterWndClass( NULL );
BOOL bCreated = this->CreateEx( 0, cstrWndClassName,
L"CMessageOnlyWindow", 0, 0, 0, 0, 0, HWND_MESSAGE, 0 );
this->RegisterNotification();
}
CMessageOnlyWindow::~CMessageOnlyWindow() {}
BEGIN_MESSAGE_MAP(CMessageOnlyWindow, CWnd)
ON_WM_DEVICECHANGE()
END_MESSAGE_MAP()
afx_msg BOOL CMessageOnlyWindow::OnDeviceChange( UINT nEventType, DWORD dwData )
{
switch ( nEventType ) // <-- Never gets here.
{
case DBT_DEVICEARRIVAL:
break;
case DBT_DEVICEREMOVECOMPLETE:
break;
default:
break;
}
return TRUE;
}
void CMessageOnlyWindow::RegisterNotification(void)
{
_pDevIF = (DEV_BROADCAST_DEVICEINTERFACE *)malloc( sizeof(DEV_BROADCAST_DEVICEINTERFACE) );
memset( _pDevIF, 0, sizeof(DEV_BROADCAST_DEVICEINTERFACE) );
_pDevIF->dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
_pDevIF->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
_pDevIF->dbcc_classguid = GUID_INTERFACE_CP210x;
_hNotifyDev = RegisterDeviceNotification( this->m_hWnd, _pDevIF, DEVICE_NOTIFY_WINDOW_HANDLE );
}
void CMessageOnlyWindow::UnregisterNotification(void)
{
UnregisterDeviceNotification( _hNotifyDev );
}
Любые мысли или предложения будут очень ценились. Если какие-либо данные отсутствуют, дайте мне знать, и я буду рад добавить их. Спасибо.
Необходимо ли запустить окно только сообщение в новом потоке, или создает новое окно автоматически выключить новую тему?
Решение
Создать пусточное окно, которое ничего не делает, кроме как ждать WM_DEVICECHANGE
и зарегистрируйте это окно, используя RegisterDeviceNotification
. Отказ WMI - это сверхугольник, ИМХО.
Другие советы
Eсть MSDN образец Специально для вашего случая, в нативном коде.
Регистрация для уведомления устройства
Лучше сделать это таким образом, чем через WMI.
Я следовал за вашим «новым подходом», а также обнаружил, что OnDeviceChange не звали. Проблема заключалась в том, что не было цикла сообщения, потому что это было консольное приложение. Вызов следующей функции на регулярных интервалах.
void check_for_device_change()
{
MSG msg;
const int val = PeekMessage( &msg, 0, 0, 0, PM_REMOVE );
if( val > 0 )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}