2012-01-04 11 views
5

Sto tentando di rilevare l'inserimento di dispositivi rimovibili e recuperare la lettera di unità di tale dispositivo utilizzando un servizio NT. Sono riuscito a rilevare l'inserimento e la rimozione di dispositivi, ma non sono stato in grado di configurare una struttura DEV_BROADCAST_VOLUME che mi consenta di ottenere la lettera dell'unità, GUID, ecc. Dal volume.Impossibile recuperare i dati su un dispositivo rimovibile utilizzando un servizio Windows in C++

case SERVICE_CONTROL_DEVICEEVENT:{ 
      switch(evtype){ 
      case DBT_DEVICEARRIVAL:{ 
        DEV_BROADCAST_VOLUME *hdr = (DEV_BROADCAST_VOLUME*) evdata; 
        ofstream log ("C:\\log.txt", ios::app); 
        log << hdr->dbcv_devicetype; 
        log.close(); 
       } 
       break; 

Il frammento di codice sopra compila e funziona correttamente, ma quando inserisco un'unità flash, hdr->dbcv_devicetype registri come valore di 55555 e DBT_DEVTYP_VOLUME (che è quello che un'unità USB) è definita come 2 (hdr->dbcv_devicetype deve uguagliare DBT_DEVTYP_VOLUME perché ho inserito un flash drive). Per qualche motivo, il DBT_DEVTYP_VOLUME non sta inizializzando correttamente, o qualcos'altro che sto facendo è sbagliato. Sto usando Windows 7 con Visual Studio 2011 C++.

+3

Avete considerato che le unità ei driver mentono? la differenza tra un "disco rigido USB esterno" e un "disco rigido USB interno" è arbitraria. Per non parlare del fatto che tecnicamente la definizione di "disco" e "volume" e Drive sono la differenza ... Oh e per i punti bonus ciò che LOCAL_SYSTEM vede come C: \ non deve essere quello che l'utente vede come c: \ – Dan

+0

Idealmente dovresti farlo nel contesto dell'utente in quanto i mapping delle lettere delle unità sono gestiti per utente. Se sei in grado di farlo, puoi semplificare enormemente il tuo compito dato che l'esploratore fa già il duro lavoro; è possibile utilizzare una semplice chiamata a SHChangeNotifyRegister() per ottenere le notifiche. – Luke

+0

@Luke L'idea sembra buona, ma continuerà a rilevare le unità che non sono montate? Ad esempio, Windows non monterà un file system Linux, semplicemente informerà l'utente di formattarlo. 'SHChangeNotifyRegister()' selezionerebbe l'inserimento anche se non è montato su una lettera di unità come 'E: \\'? – user99545

risposta

1

Prova questo:

PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)evdata; 
    if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME) 
    { 
    PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb; 

    if (lpdbv -> dbcv_flags & DBTF_MEDIA) 
    { 
     StringCchPrintf(szMsg, sizeof(szMsg)/sizeof(szMsg[0]), 
         TEXT("Drive %c: Media has arrived.\n"), 
         FirstDriveFromMask(lpdbv ->dbcv_unitmask)); 

     MessageBox(hwnd, szMsg, TEXT("WM_DEVICECHANGE"), MB_OK); 
    } 
    } 

    /*------------------------------------------------------------------ 
     FirstDriveFromMask(unitmask) 

     Description 
     Finds the first valid drive letter from a mask of drive letters. 
     The mask must be in the format bit 0 = A, bit 1 = B, bit 2 = C, 
     and so on. A valid drive letter is defined when the 
     corresponding bit is set to 1. 

     Returns the first drive letter that was found. 
    --------------------------------------------------------------------*/ 

    char FirstDriveFromMask(ULONG unitmask) 
    { 
    char i; 

    for (i = 0; i < 26; ++i) 
     { 
     if (unitmask & 0x1) 
     break; 
     unitmask = unitmask >> 1; 
     } 

    return(i + 'A'); 
    } 

Codice tirato da Detecting Media Insertion or Removal

+0

Il codice per rilevare la rimozione del dispositivo è incluso nel collegamento. –

+0

Ho dovuto modificare un po 'il codice in quanto causava alcuni errori che causavano il crash del servizio. Ho postato le modifiche [qui.] (Http://pastebin.com/3Fyb3b1p) Il problema è che ogni volta che inserisco un'unità, la lettera di unità è "A" (senza virgolette). Ho provato anche molti dispositivi. Non sei sicuro del motivo per cui ciò sta accadendo, forse è la funzione 'FirstDriveFromMask()'? Ho provato a utilizzare quel codice in un'app console Win32 e ha funzionato perfettamente, quindi sono completamente confuso qui. Deve essere qualcosa di specifico per i servizi di Windows. – user99545

+0

Bene, hanno usato il loop dei messaggi Window per ottenere il loro messaggio; tuttavia non penso che sarebbe difficile adattarsi. Riguardo al problema con solo la lettera di unità 'A' che appare, provare a rimuovere l'istruzione break e vedere quanti bit sono stati impostati. Potrebbe essere che sul tuo computer l'unità Un bit è sempre impostato e questo algoritmo si ferma alla prima lettera di unità. –

Problemi correlati