Rilevamento USB inserimento / rimozione Eventi a Windows utilizzando C ++
-
28-09-2019 - |
Domanda
vi scrivo un'estensione per un'applicazione esistente che deve gestire gli eventi di inserimento USB / rimozione. So che il VID / PID del dispositivo di interesse. Tuttavia, non ho accesso alla maniglia della finestra, quindi non so se RegisterDeviceNotification
sarà di grande utilità, a meno che non ci sia un modo per ottenere la maniglia attraverso il WINAPI
. Quale sarebbe il modo migliore per rilevare eventi di inserimento / rimozione USB con C ++?
Questo codice di esempio sul sito Web Microsoft mostra come ricevere le notifiche degli eventi tramite WMI:
Come potrebbe essere modificato per ricevere gli eventi di inserimento / rimozione USB? Oppure, c'è un altro modo che dovrei andare su questo? Sto usando Visual Studio 2008. Grazie.
informazioni aggiuntive
Questo è quello che ho finora (meno di gestione degli errori):
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);
}
Il PC entra nel WndProc
, ma non quando rimuovo / inserto mio dispositivo USB. Il PC non sembra mai entrare in OnDeviceChange
. Eventuali suggerimenti sarebbe apprezzato. Ho bisogno di gestire imprevisti inserimenti / rimozioni del dispositivo USB. Se si fa la differenza, la periferica USB appare come una porta COM virtuale a Windows. Grazie.
Info Aditional: "Impossibile trovare la classe finestra" Calling CreateWindowEx
utilizzando la atom
classe restituita dal RegisterClassEx
non riesce con il messaggio di errore,
_hWnd = CreateWindowEx( 0, (LPCTSTR)&atom, pWindowName, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL );
NUOVO APPROCCIO
Sto anche cercando di questo nuovo approccio. Sto cercando di ottenere scrivere una finestra di messaggio-solo per ricevere i messaggi di notifica di cambio per una periferica USB. Sto usando MFC, C ++ e Visual Studio 2008. compila tutto, e funziona senza crash o bloccarsi, ma il gestore di eventi è mai attivato. Il dispositivo di interesse è installato su Windows come una porta COM virtuale.
La mia applicazione principale un'istanza della classe descritto di seguito quindi attende un ingresso di carattere dalla polling della tastiera utilizzando un ciclo while. E 'durante questo tempo di attesa che io rimuovere e inserire il dispositivo USB in attesa della manifestazione di essere licenziato.
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.
};
Per semplicità, ho rimosso tutto il pulizia e di gestione degli errori:
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 );
}
Ogni pensiero o suggerimenti sarebbe molto apprezzato. Se alcuni dettagli mancanti, fatemelo sapere, e sarò felice di aggiungerli. Grazie.
La finestra di necessità messaggio-solo per essere avviato in un nuovo thread, o se creare una nuova finestra automaticamente spin off un nuovo thread?
Soluzione
Crea una finestra fittizio che non fa altro che aspettare per WM_DEVICECHANGE
e registrare quella finestra utilizzando RegisterDeviceNotification
. WMI è un peso inutile qui, IMHO.
Altri suggerimenti
C'è un href="http://msdn.microsoft.com/en-us/library/aa363432(VS.85).aspx" rel="noreferrer"> campione appositamente per il vostro caso, in codice nativo.
La registrazione per la notifica dispositivo
meglio farlo in questo modo che tramite WMI.
Ho seguito il vostro "nuovo approccio" e anche scoperto che OnDeviceChange non è stato chiamato. Il problema era che non c'era nessun ciclo di messaggi, perché era una console app. Richiamo la seguente funzione a intervalli regolari riparato.
void check_for_device_change()
{
MSG msg;
const int val = PeekMessage( &msg, 0, 0, 0, PM_REMOVE );
if( val > 0 )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}