Question

Je suis en train d'écrire une extension pour une application existante qui doit gérer les événements d'insertion USB / suppression. Je sais que le VID / PID du dispositif d'intérêt. Cependant, je n'ai pas accès à la poignée de fenêtre, donc je ne sais pas si RegisterDeviceNotification sera d'une grande utilité, à moins d'un moyen d'obtenir la poignée via le WINAPI. Quelle serait la meilleure façon de détecter des événements d'insertion / suppression USB avec C ++?

Ce code exemple sur le site Microsoft montre comment recevoir des notifications d'événements via WMI:

Comment pourrait-il être modifié pour recevoir des événements d'insertion / suppression USB? Ou, est-il une autre façon que je devrais aller à ce sujet? J'utilise Visual Studio 2008. Merci.

PLUS D'INFO

est ce que j'ai jusqu'à présent (moins de gestion des erreurs):

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

Le PC entre dans WndProc, mais pas quand je supprimer / insérer mon périphérique USB. Le PC semble ne jamais entrer dans OnDeviceChange. Des conseils seraient appréciés. Je dois gérer des insertions inattendues / absorptions du périphérique USB. Si cela fait une différence, le périphérique USB apparaît comme un port COM virtuel Windows. Merci.

Infos Additionnelle: "Vous ne trouvez pas la classe de fenêtre" Appel CreateWindowEx en utilisant la atom de classe retournée par RegisterClassEx échoue avec le message d'erreur,

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

NOUVELLE APPROCHE

Je suis aussi essayer cette nouvelle approche. Je suis en train de faire écrire une fenêtre de message uniquement pour recevoir des messages de notification de changement de périphérique pour un périphérique USB. J'utilise MFC, C ++ et Visual Studio 2008. Tout compiles, et il fonctionne sans blocage ou le verrouillage, mais le gestionnaire d'événements est jamais déclenché. Le dispositif d'intérêt est installé sur Windows comme un port COM virtuel.

Ma principale application instancie la classe décrite ci-dessous attend ensuite une entrée de caractères à partir du clavier à l'aide de vote d'une boucle while. Il est pendant ce temps d'attente que je retirer et d'insérer mon périphérique USB attendant l'événement pour faire virer.

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

Par souci de simplicité, je l'ai enlevé tout le nettoyage et la gestion des erreurs:

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

Toutes les pensées ou suggestions serait très apprécié. Si les détails manquent, laissez-moi savoir, et je serai heureux de les ajouter. Merci.

La fenêtre des messages uniquement besoin d'être lancé dans un nouveau thread, ou le fait de créer une nouvelle rotation automatiquement la fenêtre hors un nouveau thread?

Était-ce utile?

La solution

Créer une fenêtre factice qui ne fait rien, mais attendre WM_DEVICECHANGE et enregistrer cette fenêtre en utilisant RegisterDeviceNotification. WMI est un surpuissant ici, à mon humble avis.

Autres conseils

Il est un exemple MSDN spécifiquement pour votre cas, en code natif.

  

Enregistrement pour la notification de l'appareil

Il vaut mieux le faire de cette façon que via WMI.

J'ai suivi votre « nouvelle approche » et a également constaté que OnDeviceChange n'a pas été appelé. Le problème était qu'il n'y avait pas de boucle de message parce qu'il était une application console. L'appel de la fonction suivante à intervalles réguliers, il fixe.

void check_for_device_change()
{
    MSG msg; 

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

    if( val > 0 )
    { 
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    } 
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top