使用C ++检测Windows中的USB插入 /删除事件
-
28-09-2019 - |
题
我正在为现有应用程序编写一个需要处理USB插入/删除事件的扩展程序。我知道感兴趣的设备的vid/pid。但是,我无法访问窗口句柄,所以我不知道是否 RegisterDeviceNotification
除非有一种方法可以通过 WINAPI
. 。使用C ++检测USB插入/删除事件的最佳方法是什么?
此示例代码在Microsoft网站上 显示如何通过WMI接收事件通知:
如何修改接受USB插入/删除事件?或者,我应该采取另一种方式吗?我正在使用Visual Studio2008。谢谢。
附加信息
这就是我到目前为止的目标(负错误处理):
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);
}
PC进入 WndProc
, ,但是当我删除/插入USB设备时,不是。 PC似乎从未进入 OnDeviceChange
. 。任何提示都将不胜感激。我需要处理USB设备的意外插入/删除。如果有所不同,则USB设备作为Windows的虚拟COM端口出现。谢谢。
Aditional信息: 打电话 CreateWindowEx
使用课程 atom
返回 RegisterClassEx
错误消息失败:“找不到窗口类”。
_hWnd = CreateWindowEx( 0, (LPCTSTR)&atom, pWindowName, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL );
新的方法
我也在尝试这种新方法。我正在尝试获取一个只有消息的窗口,以接收USB设备的设备更改通知消息。我正在使用MFC,C ++和Visual Studio2008。一切都编译了,并且它运行时不会崩溃或锁定,但是事件处理程序从未触发。感兴趣的设备作为虚拟COM端口安装在Windows上。
我的主要应用程序实例化下面描述的类,然后使用while循环等待键盘轮询的字符输入。正是在此等待时间,我删除并插入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在这里是个过度杀伤,恕我直言。
其他提示
我遵循了您的“新方法”,还发现没有打电话给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 );
}
}