Detectando a inserção e remoção da unidade USB usando o serviço do Windows e c #

Olhando para a possibilidade de fazer um aplicativo distribuído por USB
que irá iniciar automaticamente na inserção de um stick USB e desligamento ao remover o stick

Vai usar .Net e C #.
Procurando por sugestão de como abordar isso usando c #?


Atualização: Duas soluções possíveis implementando isso como um serviço.
– replace WndProc
ou
– usando a consulta WMI com o ManagementEventWatcher

    Você pode usar o WMI, é fácil e funciona muito melhor do que a solução WndProc com serviços.

    Aqui está um exemplo simples:

    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(); 

    E é isso 🙂

    Isso funciona bem para mim, além disso, você pode descobrir mais informações sobre o 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); } 

    Adicionando a postagem de VitalyB.

    Para criar um evento onde qualquer dispositivo USB é inserido, use o seguinte:

     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(); 

    Isso aumentará um evento sempre que um dispositivo USB for conectado. Ele até funciona com um DAQ da National Instruments que estou tentando detectar automaticamente.

    A resposta de VitalyB não cobre a remoção do dispositivo. Eu mudei um pouco para acionar o evento quando a mídia é inserida e removida e também código para obter a letra da unidade da mídia inserida.

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

    Você também pode usar o WMI para detectar events de inserção. É um pouco mais complicado do que monitorar mensagens WM_CHANGEDEVICE, mas não requer um identificador de janela que pode ser útil se você estiver executando em segundo plano como um serviço.

    Tente o tratamento de WM_CHANGEDEVICE .

    Aqui está o que fizemos com C # .Net 4.0 em um aplicativo WPF. Ainda estamos procurando por uma resposta para “como saber que tipo de dispositivo foi inserido / removido”, mas isso é um começo:

      using System.Windows.Interop; ... public partial class MainWindow : Window { ... public MainWindow() { ... } //============================================================ // WINDOWS MESSAGE HANDLERS // private const int WM_DEVICECHANGE = 0x0219; // int = 537 private const int DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = 0x00000004; ///  /// ///  ///  protected override void OnSourceInitialized(EventArgs e) { base.OnSourceInitialized(e); HwndSource source = PresentationSource.FromVisual(this) as HwndSource; source.AddHook(WndProc); } private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { if (msg == WM_DEVICECHANGE) { ReadDongleHeader(); } return IntPtr.Zero; } } 

    Um pouco de edição em todas as respostas acima:

     using System.Management; public partial class MainForm : Form { public MainForm() { InitializeComponent(); bgwDriveDetector.DoWork += bgwDriveDetector_DoWork; bgwDriveDetector.RunWorkerAsync(); } private void DeviceInsertedEvent(object sender, EventArrivedEventArgs e) { string driveName = e.NewEvent.Properties["DriveName"].Value.ToString(); MessageBox.Show(driveName + " inserted"); } private void DeviceRemovedEvent(object sender, EventArrivedEventArgs e) { string driveName = e.NewEvent.Properties["DriveName"].Value.ToString(); MessageBox.Show(driveName + " removed"); } void bgwDriveDetector_DoWork(object sender, DoWorkEventArgs e) { var insertQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2"); var insertWatcher = new ManagementEventWatcher(insertQuery); insertWatcher.EventArrived += DeviceInsertedEvent; insertWatcher.Start(); var removeQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 3"); var removeWatcher = new ManagementEventWatcher(removeQuery); removeWatcher.EventArrived += DeviceRemovedEvent; removeWatcher.Start(); } }