使用 Windows 服务和 c # 检测 USB 驱动器的插入和删除

研究制作 USB 分布式应用程序的可能性
这将自动启动插入一个 U 盘和关闭时,删除 U 盘 < br/>

将使用.Net 和 C # 。
寻找如何使用 C # 实现这一点的建议?


更新: 实现此服务的两种可能的解决方案。
重写 WndProc
或者
- 在 ManagementEventWatcher 中使用 WMI 查询

101382 次浏览

还可以使用 WMI检测插入事件。这比监视 WM _ CHOGEDevICE 消息稍微复杂一些,但是它不需要窗口句柄,如果您在后台作为服务运行,那么窗口句柄可能会很有用。

你可以使用 WMI,它很容易,它比 WndProc 解决方案的服务好得多。

下面是一个简单的例子:

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

下面是我们对 C # 所做的。WPF 应用程序下的 Net 4.0。我们仍在寻找“如何判断插入/移除了哪种设备类型”的答案,但这只是一个开始:

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


}

添加到 VitalyB 的帖子。

若要引发插入 任何 USB 设备的事件,请使用以下命令:

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

这将在 USB 设备被插入时引发一个事件。它甚至可以与我正在尝试自动检测的国家仪器 DAQ 一起工作。

这对我来说很有用,另外你可以找到更多关于这个设备的信息。

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

VitalyB 的回答不包括移除设备。当介质为 插入被移除了时,我稍微改变了它来触发事件,并且还改变了获取插入介质的驱动器号的代码。

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

对以上答案稍作修改:

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


}










}


}

我的完整答案可以找到 给你作为一个要点

我从这个问题/答案中找到了确定序列号驱动器号的答案 如何使用 WMI 获取 USB 设备的驱动器号

我修改了菲尔 · 迈纳的代码让它有反应:

   public class UsbDetector : IUsbDetector
{
private const string Query = "SELECT * FROM {0} WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'";
private const string CreationEvent = "__InstanceCreationEvent";
private const string DeletionEvent = "__InstanceDeletionEvent";
private const int ReplayNumber = 1;


private readonly Subject<USBDeviceInfo> adds = new Subject<USBDeviceInfo>();
private readonly Subject<USBDeviceInfo> removes = new Subject<USBDeviceInfo>();


public UsbDetector()
{
var bgwDriveDetector = new BackgroundWorker();
bgwDriveDetector.DoWork += DoWork;
bgwDriveDetector.RunWorkerAsync();
}


public IObservable<USBDeviceInfo> Adds => adds.AsObservable();


public IObservable<USBDeviceInfo> Removes => removes.AsObservable();




private void DoWork(object sender, DoWorkEventArgs e)
{
SubscribeToEvent(CreationEvent, adds);
SubscribeToEvent(DeletionEvent, removes);
}


private static void SubscribeToEvent(string eventType, IObserver<USBDeviceInfo> observer)
{
WqlEventQuery wqlEventQuery = new WqlEventQuery(string.Format(Query, eventType));
ManagementEventWatcher insertWatcher = new ManagementEventWatcher(wqlEventQuery);


var observable = Observable.FromEventPattern<EventArrivedEventHandler, EventArrivedEventArgs>(
h => insertWatcher.EventArrived += h,
h => insertWatcher.EventArrived -= h).Replay(ReplayNumber);


observable.Connect();
observable.Select(a => a.EventArgs).Select(MapEventArgs).Subscribe(observer);
insertWatcher.Start();
}




private static USBDeviceInfo MapEventArgs(EventArrivedEventArgs e)
{
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];


string deviceId = (string)instance.GetPropertyValue("DeviceID");
string serialNr = deviceId.Substring(deviceId.LastIndexOf('\\')).Replace("\\", "");
char driveLetter = GetDriveLetter(serialNr).First();


return new USBDeviceInfo(deviceId, serialNr, driveLetter);
}