Detecting USB drive insertion and removal using windows service and c#
Solution 1
You can use WMI, it is easy and it works a lot better than WndProc solution with services.
Here is a simple example:
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();
Solution 2
This works well for me, plus you can find out more information about the device.
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);
}
Solution 3
Adding to VitalyB's post.
To raise an event where ANY USB device is inserted, use the following:
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();
This will raise an event whenever a USB device is plugged. It even works with a National Instruments DAQ that I'm trying to auto-detect.
Solution 4
VitalyB's answer does't cover remove of the device. I changed it a bit to trigger the event both when media is inserted and removed and also code to get the drive letter of the inserted media.
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();
}
}
}
Solution 5
A little bit edit on all above answer:
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();
}
}
Kb.
Currently trying to migrate complex scheduling data using C#, Teams and SQL with Dapper
Updated on September 19, 2021Comments
-
Kb. over 2 years
Looking into possibility of making an USB distributed application
that will autostart on insertion of an USB stick and shutdown when removing the stickWill use .Net and C#.
Looking for suggestion how to approach this using C#?
Update: Two possible solutions implementing this as a service.
- override WndProc
or
- using WMI query with ManagementEventWatcher -
Kb. about 15 years@John Conrad: +1 WMI is a good choice. Also found a SO topic on this: stackoverflow.com/questions/39704/…
-
VitalyB almost 14 yearsActually WMI is much simpler solution. I'm posting it below as another solution.
-
Never Quit almost 11 yearsThat works fine but How can I get drive letter of inserted USB?
-
Never Quit almost 11 years@Lee Taylor That works fine but How can I get drive letter of inserted USB?
-
Lee Taylor almost 11 years@NeverQuit - I only edited the question, ask @Syn! Also, if you have a new question then feel free to create one.
-
Never Quit almost 11 years@Syn That works fine but How can I get drive letter of inserted USB?
-
Kcvin almost 11 yearsAny improvements as to figuring out which device was inserted?
-
VitalyB over 9 yearsThis article seems to be getting this information in Powershell. Shouldn't be too hard to translate that to C#.
-
samuelesque over 9 yearsWorks perfectly. Doesn't fire multiple events like some of the other answers here on insertion/removal. This should be the accepted answer.
-
Amit Lipman almost 9 yearsHi it works great for USB insertion! the above comment with "SELECT * FROM Win32_VolumeChangeEvent WHERE EventType = 2" I don't know why but it doesn't work for me. I want the event to run both for insertion and removal. Do you now the line string which will make it happen? or where I can see all the string which the wqleventQuery receive? It's not listed on the MSDN wqleventQuery CTOR page ..
-
CularBytes about 8 years@Kevin this can easily be found elsewhere to get the list of devices. Here is a full solution which I got to first. Only WM_DEVICECHANGE is fired for me. social.msdn.microsoft.com/Forums/vstudio/en-US/…
-
lambinator almost 8 yearsIn your event handler,
e.NewEvent.Properties["DriveName"].Value.ToString()
-
helder.tavares.silva almost 8 yearsI agree with @samuelAndThe, this seems the best aproach. If you are looking for also detect changes to hard drives and not only usb drives you can use the 'Win32_DiskDrive' class
-
komodosp over 7 yearsThis is great, but for some reason it's firing the event multiple times each time I plug in or out a device - do you know why this might be and how to prevent it?
-
Ashkan Mobayen Khiabani over 7 yearsAs you haven't posted your code its hard to tell, but may be you are attaching the event more than once.
-
ch271828n almost 7 years
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
, why do you have(object sender, DoWorkEventArgs e)
???(I committed an edit suggestion for this.) -
ch271828n almost 7 yearsthis is not a full code!!! so you need to replace several lines of VitalyB's answer to this.
-
Fidel over 6 yearsNice enhancements Ashkan, it's nice to know when a drive is ejected too.
-
icbytes over 6 yearsWill this run on mono? Just asking, because started recently with that, and wmi is ms pure.
-
Kasun Koswattha over 5 yearsDeviceName is not found in the e.NewEven.Properties.
-
Pavlin Marinov over 5 yearsEverything is awesome but please remove that Thread.Sleep ^_^
-
spy about 5 yearsthe query is clearly for volume changes, which has nothing to do usb added/removed. It doesn't even work for volume changes, at least on my system
-
stackmalux almost 5 yearsusing the above query is eating cpu resources, any idea why wmi causes this issue?
-
Aditya over 4 yearsWhat's the purpose of Thread.Sleep? The DeviceInsertedEvent still fires event after the BackgroundWorker call ends after this sleep times out
-
leumasme over 4 yearsDoes this instantly trigger the event or does it check in an interval? / Is it possible for another Program / the user to read/write files from the drive before the event fires?
-
Callum Rogers about 4 yearsFor removal, you just need to do
WHERE EventType = 2 OR EventType = 3
.EventType
of2
means addition,3
means removal, as per docs.microsoft.com/en-us/windows/win32/cimwin32prov/… -
AmirSina Mashayekh almost 4 yearsI think that Thread.Sleep is there to simulate a long application code. You can simply remove it.
-
AmirSina Mashayekh almost 4 yearsIs there any way to detect Any USB device in this method? As you know other answers fire multiple events which is not good.