Detección de inserción y extracción de unidades USB mediante el servicio de Windows y C#
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
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();
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);
}
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.
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();
}
}
}