Détection de l'insertion et de la suppression d'un lecteur USB à l'aide du service Windows et de c #

StackOverflow https://stackoverflow.com/questions/620144

Question

Examen de la possibilité de créer une application distribuée par USB
qui démarrera automatiquement lors de l’insertion d’une clé USB et de son arrêt lors du retrait de la clé

Utilisera .Net et C #.
Vous cherchez des suggestions sur la façon d’aborder ceci avec C #?


Mise à jour: Deux solutions possibles mettant en œuvre cela en tant que service.
- écrasement WndProc
ou
- en utilisant une requête WMI avec ManagementEventWatcher

Était-ce utile?

La solution

Vous pouvez utiliser WMI, c’est simple et fonctionne beaucoup mieux que la solution WndProc avec services.

Voici un exemple 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();

Autres conseils

Cela fonctionne bien pour moi et vous pouvez en savoir plus sur le périphérique.

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

Ajout au message de VitalyB.

Pour déclencher un événement où un TOUT périphérique USB est inséré, utilisez les éléments suivants:

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

Cela déclenchera un événement chaque fois qu'un périphérique USB est branché. Cela fonctionne même avec un DAQ de National Instruments que je tente de détecter automatiquement.

La réponse de VitalyB ne couvre pas le retrait de l'appareil. Je l'ai un peu modifié pour déclencher l'événement lorsque le média est inséré et supprimé , ainsi que le code permettant d'obtenir la lettre de lecteur du média inséré.

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

Modifiez un peu la réponse ci-dessus:

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

Vous pouvez également utiliser WMI pour détecter les événements d'insertion. C’est un peu plus compliqué que de surveiller les messages WM_CHANGEDEVICE, mais il n’exige pas de gestionnaire de fenêtre, ce qui peut être utile si vous exécutez l’arrière-plan en tant que service.

Essayez de WM_CHANGEDEVICE . p>

Voici ce que nous avons fait avec C # .Net 4.0 sous une application WPF. Nous sommes toujours à la recherche d’une réponse à la question "Comment savoir quel type de périphérique a été inséré / supprimé", mais c’est un début:

    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; 

    /// <summary>
    ///
    /// </summary>
    /// <param name="e"></param>
    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;
    }

}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Management;
using System.ComponentModel;

namespace ConsoleApplication4
{
  public  class usbState
    {
       public usbState()
        {

        }

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

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

}



class Class1
{
       private static void Main(string[] args)
      {
          usbState  usb= new usbState();



          BackgroundWorker bgwDriveDetector = new BackgroundWorker();
          bgwDriveDetector.DoWork += usb.bgwDriveDetector_DoWork;
          bgwDriveDetector.RunWorkerAsync();
          bgwDriveDetector.WorkerReportsProgress = true;
          bgwDriveDetector.WorkerSupportsCancellation = true;

         // System.Threading.Thread.Sleep(100000);
           Console.ReadKey();

       }





}

}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top