Subscribe to the Inserted and Removed events to be notified when a USB drive is plugged in or unplugged, or when a USB device is connected or disconnected. Usb.Events is a .NET Standard 2.0 library and uses WMI on Windows, libudev on Linux and IOKit on macOS.
Subscribe to the Inserted and Removed events to be notified when a USB drive is plugged in or unplugged, or when a USB device is connected or disconnected. Usb.Events is a .NET Standard 2.0 library and uses WMI on Windows, libudev on Linux and IOKit on macOS.
Include NuGet package from https://www.nuget.org/packages/Usb.Events
<ItemGroup>
<PackageReference Include="Usb.Events" Version="11.1.0.1" />
</ItemGroup>
Subscribe to events:
using Usb.Events;
class Program
{
static void Main(string[] _)
{
using IUsbEventWatcher usbEventWatcher = new UsbEventWatcher();
usbEventWatcher.UsbDeviceRemoved += (_, device) => Console.WriteLine("Removed:" + Environment.NewLine + device + Environment.NewLine);
usbEventWatcher.UsbDeviceAdded += (_, device) => Console.WriteLine("Added:" + Environment.NewLine + device + Environment.NewLine);
usbEventWatcher.UsbDriveEjected += (_, path) => Console.WriteLine("Ejected:" + Environment.NewLine + path + Environment.NewLine);
usbEventWatcher.UsbDriveMounted += (_, path) =>
{
Console.WriteLine("Mounted:" + Environment.NewLine + path + Environment.NewLine);
foreach (string entry in Directory.GetFileSystemEntries(path))
Console.WriteLine(entry);
Console.WriteLine();
};
Console.ReadLine();
}
}
UsbEventWatcher(
bool startImmediately = true,
bool addAlreadyPresentDevicesToList = false,
bool usePnPEntity = false,
bool includeTTY = false)
startImmediately
to false
if you don't want to start immediately, then call Start()
.addAlreadyPresentDevicesToList
to true
to include already present devices in UsbDeviceList
.usePnPEntity
to true
to query Win32_PnPEntity
instead of Win32_USBControllerDevice
in Windows.includeTTY
to true
to monitor the TTY
subsystem in Linux (besides the USB
subsystem).Win32_PnPEntity
vs Win32_USBControllerDevice
Win32_PnPEntity
MountedDirectoryPath
for storage devices (this should still work for most devices)Win32_USBControllerDevice
MountedDirectoryPath
for storage devicesUsbDeviceAdded
event after the device is added and removed a few timesUsing Win32_USBControllerDevice
is usually the better option.
Usb.Events.Example
demonstrates how to use Windows SetupAPI.dll
functions SetupDiGetClassDevs, SetupDiEnumDeviceInfo and SetupDiGetDeviceProperty together with DEVPKEY_Device_DeviceDesc, DEVPKEY_Device_BusReportedDeviceDesc and DEVPKEY_Device_FriendlyName to get "Device description", "Bus reported device description" and "Friendly name" of the Usb.Events.UsbDevice
reported by the Usb.Events.IUsbEventWatcher.UsbDeviceAdded
event.
Usb.Events.csproj
uses gcc
to build UsbEventWatcher.Mac.dylib
from UsbEventWatcher.Mac.c
when run on macOS and to build UsbEventWatcher.Linux.so
from UsbEventWatcher.Linux.c
when run on Linux.
On Debian/Ubuntu based Linux distros you need to install:
gcc with:
sudo apt-get install build-essential
32-bit and 64-bit udev with:
sudo apt-get install libudev-dev:i386 libudev-dev:amd64
support for compiling 32-bit on 64-bit Linux:
sudo apt-get install gcc-multilib
Usb.Events.dll
expects to find UsbEventWatcher.Linux.so
and UsbEventWatcher.Mac.dylib
in the working directory when it runs, so make sure to build the project on Linux and Mac before building the NuGet package on Windows.
32-bit Intel macOS:
gcc -shared -m32 ./Mac/UsbEventWatcher.Mac.c -o ./x86/Release/UsbEventWatcher.Mac.dylib -framework CoreFoundation -framework DiskArbitration -framework IOKit
32-bit Intel Linux:
gcc -shared -m32 ./Linux/UsbEventWatcher.Linux.c -o ./x86/Release/UsbEventWatcher.Linux.so -ludev -fPIC
64-bit Intel macOS:
gcc -shared -m64 ./Mac/UsbEventWatcher.Mac.c -o ./x64/Release/UsbEventWatcher.Mac.dylib -framework CoreFoundation -framework DiskArbitration -framework IOKit
64-bit Intel Linux:
gcc -shared -m64 ./Linux/UsbEventWatcher.Linux.c -o ./x64/Release/UsbEventWatcher.Linux.so -ludev -fPIC
32-bit ARM macOS:
gcc -shared -march=armv7-a+fp ./Mac/UsbEventWatcher.Mac.c -o ./arm/Release/UsbEventWatcher.Mac.dylib -framework CoreFoundation -framework DiskArbitration -framework IOKit
32-bit ARM Linux:
gcc -shared -march=armv7-a+fp ./Linux/UsbEventWatcher.Linux.c -o ./arm/Release/UsbEventWatcher.Linux.so -ludev -fPIC
64-bit ARM macOS:
gcc -shared -march=armv8-a ./Mac/UsbEventWatcher.Mac.c -o ./arm64/Release/UsbEventWatcher.Mac.dylib -framework CoreFoundation -framework DiskArbitration -framework IOKit
64-bit ARM Linux:
gcc -shared -march=armv8-a ./Linux/UsbEventWatcher.Linux.c -o ./arm64/Release/UsbEventWatcher.Linux.so -ludev -fPIC
To build 32-bit and 64-bit ARM versions of UsbEventWatcher.Linux.so
on Windows, you need to install Docker.
UsbDeviceAdded
event in LinuxUsbDeviceAdded
event in macOSUsbEvents.snk
to sign the assembly with a strong name keyInvalidOperationException
in Linux and macOS - by @Frankh67
Dispose()
to exit native monitor loop in macOSDispose()
to exit native monitor loop in Linuxbool usePnPEntity
to use Win32_PnPEntity
in Windowsbool addAlreadyPresentDevicesToList
in WindowsSystem.Management
package reference from 4.7.0
to 7.0.0
bool startImmediately = true
to UsbEventWatcher
constructorvoid Start(bool includeTTY = false)
to IUsbEventWatcher
bool includeTTY = false
to UsbEventWatcher
constructorEnumerateDevices
bug in Linux - thanks to @d79ima
NullReferenceException
in Linux and macOS - by @thomOrbelius
MountedDirectoryPath
wasn't set for a disk drive - thanks to @cksoft0807
GetLinuxMountPoint
- by @maskimthedog
UsbEventWatcher
, the list of devices was empty - by @maskimthedog
TTY
subsystem in Linux - by @maskimthedog
MountedDirectoryPath
IsMounted
IsEjected
DevicePath
renamed to DeviceSystemPath
UsbDriveInserted
renamed to UsbDriveMounted
UsbDriveRemoved
renamed to UsbDriveEjected
UsbDeviceInserted
renamed to UsbDeviceAdded