Pregunta

Yo escribo una extensión de una aplicación existente que necesita para controlar los eventos de inserción USB / eliminación. Sé el VID / PID del dispositivo de interés. Sin embargo, no tengo acceso a la manija de la ventana, así que no sé si RegisterDeviceNotification será de mucha utilidad, a menos que haya una manera de obtener el identificador a través de la WINAPI. ¿Cuál sería la mejor manera de detectar eventos de inserción / extracción USB con C ++?

Este código de ejemplo en la página web de Microsoft muestra cómo recibir notificaciones de eventos a través de WMI:

Como no podía ser modificado para recibir eventos de inserción / extracción USB? O, ¿hay otra forma en que debería ir sobre esto? Estoy utilizando Visual Studio 2008. Gracias.

INFORMACIÓN ADICIONAL

Esto es lo que tengo hasta ahora (menos de manejo de errores):

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

El PC se mete en WndProc, pero no cuando me retire / insertar el dispositivo USB. El PC no parece entrar en OnDeviceChange. Cualquier extremidad sería apreciada. Necesito manejar inesperados inserciones / eliminaciones de dispositivo USB. Si se hace una diferencia, el dispositivo USB aparece como un puerto COM virtual a Windows. Gracias.

Información Adicional: "No se puede encontrar la clase de ventana" Llamando CreateWindowEx utilizando la clase atom devuelto por RegisterClassEx falla con el mensaje de error

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

NUEVO ENFOQUE

También estoy tratando de este nuevo enfoque. Estoy intentando conseguir escribir una ventana de mensaje de sólo recibir mensajes de notificación de cambio de dispositivo para un dispositivo USB. Estoy utilizando MFC, C ++ y Visual Studio 2008. compila todo, y se ejecuta sin que se caiga o encerrar, pero el controlador de eventos no se activa. El dispositivo de interés está instalado en Windows como un puerto COM virtual.

Mi principal aplicación crea la instancia de la clase se describe a continuación espera entonces una entrada de caracteres desde el sondeo del teclado utilizando un bucle while. Es durante este tiempo de espera que desconectar y conectar el dispositivo USB esperando el caso de ser despedido.

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, me he quitado toda la limpieza y tratamiento de errores:

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

Cualquier idea o sugerencia sería muy apreciada. Si cualquier faltan detalles, que me haga saber, y estaré contento de añadirlas. Gracias.

¿Es necesario que la ventana de sólo mensajes que se inició en un nuevo tema, o no crear una nueva ventana de forma automática spin off un nuevo hilo?

¿Fue útil?

Solución

Crea una ventana ficticia que no hace más que esperar a que WM_DEVICECHANGE y registrar esa ventana usando RegisterDeviceNotification. WMI es una exageración aquí, en mi humilde opinión.

Otros consejos

Hay una muestra MSDN específicamente para su caso, en código nativo.

  

El registro para notificación del dispositivo

Es mejor hacerlo de esta manera que a través de WMI.

He seguido su "nuevo enfoque" y también encontró que OnDeviceChange no estaba siendo llamado. El problema era que no había ningún bucle de mensajes porque era una aplicación de consola. Llamando a la siguiente función a intervalos regulares fijada a él.

void check_for_device_change()
{
    MSG msg; 

    const int val = PeekMessage( &msg, 0, 0, 0, PM_REMOVE );

    if( val > 0 )
    { 
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    } 
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top