2010-04-14 22 views
2

J'essaie de détecter qu'un lecteur de disque USB est inséré dans un service Windows, c'est ce que j'ai fait en tant qu'application Windows normale. Le problème est que le code suivant ne fonctionne pas pour les volumes.Détection d'un lecteur USB en cours d'insertion - Service Windows

Enregistrement de la notification de l'appareil:

DEV_BROADCAST_DEVICEINTERFACE notificationFilter; 
    HDEVNOTIFY hDeviceNotify = NULL;   

    ::ZeroMemory(&notificationFilter, sizeof(notificationFilter)); 

    notificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); 
    notificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; 
    notificationFilter.dbcc_classguid = ::GUID_DEVINTERFACE_VOLUME; 

    hDeviceNotify = ::RegisterDeviceNotification(g_serviceStatusHandle, &notificationFilter, DEVICE_NOTIFY_SERVICE_HANDLE); 

Le code de la fonction ServiceControlHandlerEx:

case SERVICE_CONTROL_DEVICEEVENT: 
    PDEV_BROADCAST_HDR pBroadcastHdr = (PDEV_BROADCAST_HDR)lpEventData; 

    switch (dwEventType) 
    { 
    case DBT_DEVICEARRIVAL: 
     ::MessageBox(NULL, "A Device has been plugged in.", "Pounce", MB_OK | MB_ICONINFORMATION); 

     switch (pBroadcastHdr->dbch_devicetype) 
     { 
     case DBT_DEVTYP_DEVICEINTERFACE: 
      PDEV_BROADCAST_DEVICEINTERFACE pDevInt = (PDEV_BROADCAST_DEVICEINTERFACE)pBroadcastHdr; 

      if (::IsEqualGUID(pDevInt->dbcc_classguid, GUID_DEVINTERFACE_VOLUME)) 
      { 
       PDEV_BROADCAST_VOLUME pVol = (PDEV_BROADCAST_VOLUME)pDevInt; 

       char szMsg[80]; 
       char cDriveLetter = ::GetDriveLetter(pVol->dbcv_unitmask); 

       ::wsprintfA(szMsg, "USB disk drive with the drive letter '%c:' has been inserted.", cDriveLetter); 
       ::MessageBoxA(NULL, szMsg, "Pounce", MB_OK | MB_ICONINFORMATION); 
      } 
     } 

     return NO_ERROR; 
    } 

Dans une application Windows, je suis en mesure d'obtenir le DBT_DEVTYP_VOLUME dans dbch_devicetype, mais ce n'est pas présent dans une implémentation de Windows Service. Est-ce que quelqu'un a vu ou entendu parler d'une solution à ce problème, sans l'évident, réécrire comme une application Windows?

+0

Qu'est-ce qui ne fonctionne pas exactement? Je l'ai fait il y a quelques mois et j'ai réussi à le faire fonctionner. – Luke

+1

J'ai regardé cela avant et je n'ai pas pu obtenir DBT_DEVTYP_VOLUME non plus. La vérification du GUID est la solution de contournement que j'ai utilisée, tout comme vous le faites. Je suis probablement épais, mais qu'est-ce que vous essayez d'accomplir que de vérifier le GUID ne vous donne pas? – snowcrash09

+1

Je viens de remarquer que vous le lancez en tant que DEV_BROADCAST_VOLUME; c'est faux. Il s'agit d'un DEV_BROADCAST_DEVICEINTERFACE et vous devez obtenir le nom du lecteur à partir du nom du périphérique. – Luke

Répondre

2

Windows 7 prend en charge les "services déclenchés par déclenchement". Si vous voulez démarrer votre service, contourner une boucle de veille et réagir chaque fois que quelque chose est branché, je pense que vous feriez mieux (en supposant que Windows 7 est une option) avec un service déclenché par le démarrage du système d'exploitation lorsqu'un périphérique USB est branché. (Il existe d'autres déclencheurs mais vous avez mentionné celui-ci.)

L'exemple d'application XP2Win7 (http://code.msdn.microsoft.com/XP2Win7) inclut cette fonctionnalité. Il vient avec le code source complet. La plupart sont en VB et C# mais la partie des services déclenchés par le déclencheur est en C++ (natif).

+0

Malheureusement, je ne veux pas limiter mon service à Windows 7 seulement. –