Club.NET Almería

Plataforma .NET de Ingenieros/Ingenieros Técnicos en Informática de Almería
¡Bienvenid@ a Club.NET Almería! Iniciar sesión | ÚNETE a la web | Ayuda
en Buscar
Principal Blogs Foros Imágenes Descargas

Detección de dispositivos USB

Último artículo 06-11-2007, 12:25 escrito por karloch. 4 respuestas.
Ordenar mensajes: Anterior Siguiente
  •  06-04-2007, 4:47 1362

    Detección de dispositivos USB

    Tal vez nos haga falta hacer un programita que acceda a dispositivos usb, pero no sabemos cómo hacerlo en C#....

    Para ello, nada mejor que tomar nota de este código (Pegar en cualquier aplicación "Windows.Forms"):

     

    using System.Runtime.InteropServices;

    .... 

             //Gestión de conexiones de artefactos USB!!
            [StructLayout(LayoutKind.Sequential)]
            public struct DEV_BROADCAST_VOLUME
            {
                public int dbcv_size;
                public int dbcv_devicetype;
                public int dbcv_reserved;
                public int dbcv_unitmask;
            }

            protected override void WndProc(ref Message m)
            {
                //Estas definiciones están en dbt.h y winuser.h
                const int WM_DEVICECHANGE = 0x0219; //Se ha producido un cambio en los dispositivos
                const int DBT_DEVICEARRIVAL = 0x8000;  // El sistema detecta un nuevo dispositivo
                const int DBT_DEVICEQUERYREMOVE    = 0x8001;   //Solicita retirada del dispositivo
                const int DBT_DEVICEQUERYREMOVEFAILED = 0x8002; //Ha fallado la retirada del dispositivo
                const int DBT_DEVICEREMOVEPENDING = 0x8003; //Pendiente extracción del dispositivo
                const int DBT_DEVICEREMOVECOMPLETE = 0x8004; //Dispositivo extraído del sistema
                const int DBT_DEVICETYPESPECIFIC = 0x8005;
                const int DBT_DEVTYP_VOLUME = 0x00000002;  // logical volume
                switch (m.Msg)
                {
                    case WM_DEVICECHANGE:
                        switch (m.WParam.ToInt32())
                        {
                            case DBT_DEVICEARRIVAL:
                                {
                                    int devType = Marshal.ReadInt32(m.LParam, 4);
                                    if (devType == DBT_DEVTYP_VOLUME)
                                    {
                                        DEV_BROADCAST_VOLUME vol;
                                        vol = (DEV_BROADCAST_VOLUME)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_VOLUME));
                                        MessageBox.Show("Insertado dispositivo USB");
                                    }
                                }
                                break;
                            case DBT_DEVICEREMOVECOMPLETE:
                                MessageBox.Show("Dispositivo retirado.");
                                break;  
                        }

                        break;
                }
                //Finalmente, usar el manejador predeterminado
                base.WndProc(ref m);
            }

     

     

    ¿Qué hace el código? Fácil: Sobreescribe el manejador no administrado (el código generado por .NET es "código administrado", para evitar en la medida de lo posible fallos de memoria y etc; pero cada aplicación ha de recibir mensajes del kernel, y como no está en .NET, no es administrado, así que los mensajes que envía tampoco lo son). El nuevo manejador distingue en el mensaje una serie de flags. Concretamente, lo que nos interesa es detectar el evento de "cambio en los dispositivos", con el flag constante WM_DEVICECHANGE, y al comprobar que cambia alguno, a su vez comprobar los bits de "llegada de dispositivo" y "retirada de dispositivo". El significado de los bits más significativos está detallado en las otras constantes del método (al compilar, se subrayan en verde las que no se utilizan, pero las he puesto todas por completitud). Finalmente, el "base.WndProc(ref m);" se encarga de ejecutar el manejador predeterminado de la ventana.

    ¿Cómo identificar la letra de unidad de dispositivo? Consultando al campo "vol.dbcv_unitmask" cuando el dispositivo es detectado. Está en formato máscara de bits, de forma que el primer bit significa "A", el segundo "B", etc. (Aún tengo que buscar una forma de comprobar esto correctamente).

    ¿Para qué sirve? Por ejemplo, puedo hacer un programita que copie automágicamente los contenidos de una carpeta en el pendrive en mi carpeta de usuario, para así "sincronizar documentos" (o todo el contenido del pendrive), o que busque en el usb una clave pública RSA para iniciar sesión en algún programa... También debería funcionar con la detección de tarjetas SD (Que pueden incluir protección criptográfica contra copia de datos), de forma que el dispositivo de login sea una tarjeta SD, para guardar las fotos en su carpeta correspondiente y subirlas a una web, para borrar automáticamente el pendrive/tarjetaSD/DiscoDuroExterno al insertarlo (esta es una putada gorda)...

    Por cierto, aquí hay otro ejemplo de uso de una aplicación así... 


    Fullbyte Alchemist
  •  06-05-2007, 14:01 1375 en respuesta a 1362

    Re: Detección de dispositivos USB

    Bueno, este código funciona también con lectores de tarjetas de memoria integradas (generalmente en portátiles), y en general cualquier unidad de disco extraible al montarse (Incluidos los CD's y DVD's).

    Aunque esta nueva comunicación es para pegar un trocito de código que resuelve una de las cuestiones abiertas anteriormente: cómo detectar la LETRA de la unidad recién detectada:

    char LetraUnidad(int unitmask)
            {
                char[] units ={ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
                int i = 0;
                System.Collections.BitArray ba = new System.Collections.BitArray(System.BitConverter.GetBytes(unitmask));
                foreach (bool var in ba)
                {
                    if (var == true)
                        break;
                    i++;
                }
                return units[i];
            }

    Básicamente convierte la máscara de bits (no manejada) en un array de bits, lo recorre, y luego devuelve la letra indexada en el array de unidades válidas. En C/C++ habría usado directamente el índice para convertirlo de 'short' a 'char', pero C# y su protección de tipos no me deja hacerlo directamente.

    Bueno, a disfrutar de la detección de unidades de disco extraíbles!! Y a darle buen uso (como copia automatizada de las fotos de la tarjeta de la cámara a una carpeta en "mis imágenes", por ejemplo).

    Espero que se le de un uso responsable a este conocimiento :)

    Un saludo !

     

    PD: he compilado todo esto en un único post, para los perezosos del copiar y pegar. Está en mi blog.


    Fullbyte Alchemist
    Archivado en: ,,,
  •  06-09-2007, 11:14 1395 en respuesta a 1362

    Re: Detección de dispositivos USB

    amarquez:
    ¿Qué hace el código? Fácil: Sobreescribe el manejador no administrado (el código generado por .NET es "código administrado", para evitar en la medida de lo posible fallos de memoria y etc; pero cada aplicación ha de recibir mensajes del kernel, y como no está en .NET, no es administrado, así que los mensajes que envía tampoco lo son). El nuevo manejador distingue en el mensaje una serie de flags. Concretamente, lo que nos interesa es detectar el evento de "cambio en los dispositivos", con el flag constante WM_DEVICECHANGE, y al comprobar que cambia alguno, a su vez comprobar los bits de "llegada de dispositivo" y "retirada de dispositivo".

    ¿Quiere decir que en Windows Vista no sería necesario sobreescribir el manejador? Sería interesante saber hasta qué punto Windows Vista sigue apoyándose en Win32 y que parte está migrada a .NET.

  •  06-09-2007, 11:54 1397 en respuesta a 1395

    Re: Detección de dispositivos USB

    Habrá que ver... lo que tengo claro es que no me instalo vista hasta que no salga el Service Pack 1 :p

    Fullbyte Alchemist
  •  06-11-2007, 12:25 1402 en respuesta a 1397

    Re: Detección de dispositivos USB

    Yo ya instalé Windows Vista en mi portátil y la verdad es que me fue un poco mal, sobre todo porque Acer parece que no va darle soporte con controladores y actualizaciones de la BIOS. En estos casos utilidades como el Norton Ghost son vuestras mejores amigas para volver a tener vuestro Windows XP tal como lo dejásteis antes de la "actualización" a Vista.

    Supongo que después de los exámenes me lanzaré a probarlo en el sobremesa, a ver que tal se porta ahí. 

Ver como una fuente de noticias RSS en XML
Ofrecido por Community Server (Personal Edition)