Detección de inserción y extracción de unidades USB mediante el servicio de Windows y C#

Resuelto Kb. asked hace 15 años • 10 respuestas

Analizando la posibilidad de crear una aplicación distribuida por USB
que se inicie automáticamente al insertar una memoria USB y se apague al retirarla.

Utilizará .Net y C#.
¿Busca sugerencias sobre cómo abordar esto usando C#?


Actualización: dos posibles soluciones para implementar esto como un servicio.
- anular WndProc
o
- usar la consulta WMI con ManagementEventWatcher

Kb. avatar Mar 07 '09 02:03 Kb.
Aceptado

Puede usar WMI, es fácil y funciona mucho mejor que la solución WndProc con servicios.

Aquí hay un ejemplo simple:

using System.Management;

ManagementEventWatcher watcher = new ManagementEventWatcher();
WqlEventQuery query = new WqlEventQuery("SELECT * FROM Win32_VolumeChangeEvent WHERE EventType = 2");
watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
watcher.Query = query;
watcher.Start();
watcher.WaitForNextEvent();
VitalyB avatar Jun 07 '2010 10:06 VitalyB

Esto funciona bien para mí, además puedes encontrar más información sobre el dispositivo.

using System.Management;

private void DeviceInsertedEvent(object sender, EventArrivedEventArgs e)
{
    ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
    foreach (var property in instance.Properties)
    {
        Console.WriteLine(property.Name + " = " + property.Value);
    }
}

private void DeviceRemovedEvent(object sender, EventArrivedEventArgs e)
{
    ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
    foreach (var property in instance.Properties)
    {
        Console.WriteLine(property.Name + " = " + property.Value);
    }
}            

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    WqlEventQuery insertQuery = new WqlEventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");

    ManagementEventWatcher insertWatcher = new ManagementEventWatcher(insertQuery);
    insertWatcher.EventArrived += new EventArrivedEventHandler(DeviceInsertedEvent);
    insertWatcher.Start();

    WqlEventQuery removeQuery = new WqlEventQuery("SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");
    ManagementEventWatcher removeWatcher = new ManagementEventWatcher(removeQuery);
    removeWatcher.EventArrived += new EventArrivedEventHandler(DeviceRemovedEvent);
    removeWatcher.Start();

    // Do something while waiting for events
    System.Threading.Thread.Sleep(20000000);
}
Phil Minor avatar Oct 17 '2013 19:10 Phil Minor

Agregando a la publicación de VitalyB.

Para generar un evento en el que se inserta CUALQUIER dispositivo USB, utilice lo siguiente:

var watcher = new ManagementEventWatcher();
var query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2");
watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
watcher.Query = query;
watcher.Start();

Esto generará un evento cada vez que se conecte un dispositivo USB. Incluso funciona con un DAQ de National Instruments que estoy intentando detectar automáticamente.

Syn avatar Dec 11 '2012 18:12 Syn

La respuesta de VitalyB no cubre la extracción del dispositivo. Lo cambié un poco para activar el evento cuando se insertan y retiran medios y también el código para obtener la letra de unidad de los medios insertados.

using System;
using System.Management;

namespace MonitorDrives
{
    class Program
    {
        public enum EventType
        {
            Inserted = 2,
            Removed = 3
        }

        static void Main(string[] args)
        {
            ManagementEventWatcher watcher = new ManagementEventWatcher();
            WqlEventQuery query = new WqlEventQuery("SELECT * FROM Win32_VolumeChangeEvent WHERE EventType = 2 or EventType = 3");

            watcher.EventArrived += (s, e) =>
            {
                string driveName = e.NewEvent.Properties["DriveName"].Value.ToString();
                EventType eventType = (EventType)(Convert.ToInt16(e.NewEvent.Properties["EventType"].Value));

                string eventName = Enum.GetName(typeof(EventType), eventType);

                Console.WriteLine("{0}: {1} {2}", DateTime.Now, driveName, eventName);
            };

            watcher.Query = query;
            watcher.Start();

            Console.ReadKey();
        }
    }
}
Ashkan Mobayen Khiabani avatar Feb 23 '2016 21:02 Ashkan Mobayen Khiabani