Detectando eventos de inserção / remoção de USB no Windows usando C ++

Estou escrevendo uma extensão para um aplicativo existente que precisa lidar com eventos de inserção / remoção de USB. Conheço o VID / PID do dispositivo de seu interesse. No entanto, não tenho acesso ao identificador da janela, então não sei seRegisterDeviceNotification será de grande utilidade, a menos que haja uma maneira de obter o identificador através doWINAPI. Qual seria a melhor maneira de detectar eventos de inserção / remoção de USB com C ++?

Este código de exemplo no site da Microsoft mostra como receber notificações de eventos via WMI:

Como ele pode ser modificado para receber eventos de inserção / remoção de USB? Ou existe outra maneira de eu fazer isso? Estou usando o Visual Studio 2008. Obrigado.

INFORMAÇÃO ADICIONAL

Isto é o que eu tenho até agora (menos tratamento de erros):

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);
}

O PC entra emWndProc, mas não quando removo / insiro meu dispositivo USB. O PC nunca parece entrar emOnDeviceChange. Qualquer dica seria apreciada. Preciso lidar com inserções / remoções inesperadas do dispositivo USB. Se isso faz diferença, o dispositivo USB aparece como uma porta COM virtual para o Windows. Obrigado.

Informações adicionais: ChamandoCreateWindowEx usando a classeatom retornado porRegisterClassEx falha com a mensagem de erro "Não foi possível encontrar a classe da janela".

_hWnd = CreateWindowEx( 0, (LPCTSTR)&atom, pWindowName, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL );

NOVA ABORDAGEM

Eu também estou tentando essa nova abordagem. Estou tentando escrever uma janela somente para receber mensagens de notificação de alteração de dispositivo para um dispositivo USB. Estou usando MFC, C ++ e Visual Studio 2008. Tudo é compilado e executado sem travar ou travar, mas o manipulador de eventos nunca é acionado. O dispositivo de interesse é instalado no Windows como uma porta COM virtual.

Meu aplicativo principal instancia a classe descrita abaixo e aguarda a entrada de caracteres da pesquisa de teclado usando um loop while. É durante esse tempo de espera que removo e insiro meu dispositivo USB esperando que o evento seja acionado.

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.
};

Para simplificar, removi toda a limpeza e tratamento de erros:

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 );
}

Quaisquer pensamentos ou sugestões serão muito apreciados. Se algum detalhe estiver faltando, entre em contato e ficarei feliz em adicioná-lo. Obrigado.

A janela somente de mensagem precisa ser iniciada em um novo thread ou a criação de uma nova janela gera automaticamente um novo thread?

questionAnswers(3)

yourAnswerToTheQuestion