2012-01-04 21 views
5

Estoy tratando de detectar la inserción de dispositivos extraíbles y recuperar la letra de la unidad de dicho dispositivo con un servicio NT. He tenido éxito en detectar la inserción y eliminación de dispositivos, pero no he podido configurar una estructura DEV_BROADCAST_VOLUME que me permita obtener la letra de la unidad, el GUID, etc. del volumen.No se pueden recuperar datos en un dispositivo extraíble utilizando un servicio de Windows en 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; 

El fragmento de código anterior compila y se ejecuta correctamente, pero cuando inserto una unidad flash, hdr->dbcv_devicetype registros como un valor de 55555 y DBT_DEVTYP_VOLUME (que es lo que es una unidad USB) se define como 2 (hdr->dbcv_devicetype debe ser igual DBT_DEVTYP_VOLUME porque inserté una unidad flash). Por algún motivo, o bien el DBT_DEVTYP_VOLUME no se está inicializando correctamente, o bien, estoy haciendo algo más que está mal. Estoy usando Windows 7 con Visual Studio 2011 C++.

+3

¿Ha considerado que las unidades y los conductores se encuentran? la diferencia entre un "disco duro USB externo" y un "disco duro USB interno" es arbitraria. Sin mencionar que técnicamente la definición de "disco" y "volumen" y Drive son diferentes ... Ah, y para los puntos de bonificación, lo que LOCAL_SYSTEM ve como C: \ no tiene que ser lo que el usuario ve como c: \ – Dan

+0

Idealmente, debe hacer esto en el contexto del usuario ya que las asignaciones de letra de unidad se administran por usuario. Si eres capaz de hacer eso, entonces puedes simplificar enormemente tu tarea ya que el explorador ya hace el trabajo duro; puede usar una simple llamada a SHChangeNotifyRegister() para obtener las notificaciones. – Luke

+0

@Luke Esa idea suena bien, pero ¿seguirá detectando unidades que no están montadas? Por ejemplo, Windows no montará un sistema de archivos Linux, solo informará al usuario para formatearlo. ¿'SHChangeNotifyRegister()' levantará la inserción aunque no esté montada en una letra de unidad como 'E: \\'? – user99545

Respuesta

1

Prueba esto:

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

Código promocionado de Detecting Media Insertion or Removal

+0

El código para detectar la eliminación del dispositivo se incluye en el enlace. –

+0

Tuve que modificar tu código un poco ya que estaba arrojando algunos errores que bloquearon el servicio. Publiqué los cambios [aquí.] (Http://pastebin.com/3Fyb3b1p) El problema es que cada vez que inserto una unidad, dice que la letra de la unidad es 'A' (sin comillas). Probé muchos dispositivos también. No estoy seguro de por qué está sucediendo esto, tal vez sea la función 'FirstDriveFromMask()'? Intenté usar ese código en una aplicación de consola win32 y funcionaba perfectamente, así que estoy completamente confundido aquí. Debe ser algo específico de los Servicios de Windows. – user99545

+0

Bueno, usaron el bucle de mensaje de la ventana superior para obtener su mensaje; sin embargo, no creo que sea tan difícil adaptarse. En relación con el problema de que solo aparece la letra de la unidad 'A', intente eliminar la declaración de interrupción y vea cuántos bits se han establecido. Puede ser que en su computadora el bit de la unidad A esté siempre configurado y este algoritmo se detenga en la primera letra de la unidad. –

Cuestiones relacionadas