Managed Windows device libraries for .NET Framework 4.8, .NET Standard 2.0, and .NET 8+. Focused on basic communication with custom USB devices that use Windows "driverless" I/O — Arduino boards, bootloaders, digital scales, lab instruments, LED controllers, and similar embedded hardware.
Two independent NuGet packages — Serial (COM port) and HID (Human Interface Device) — built on a shared core of Win32 P/Invoke, device discovery, and async I/O infrastructure.
SerialPort was designed for fixed RS232 ports in the .NET 1.1 era and has well-known problems with modern USB devices:
| Problem | System.IO.Ports.SerialPort |
Anp.Serial.Win32 |
|---|---|---|
| Device disconnect | Throws on a background thread, often crashes the process or leaves the port in an unrecoverable state | Raises SerialDisconnectedException on the calling thread; device transitions cleanly to closed |
| Discovery | GetPortNames() returns bare COM names with no metadata, no VID/PID, and stale entries for disconnected devices |
SerialDiscovery.GetDevices() with VID/PID filtering, FriendlyName, and stable device paths |
| Hot-plug | None | SerialWatcher with arrival/removal events (Windows 8+) |
| Async I/O | BaseStream only; no per-call timeout, no cancellation |
ReadAsync / WriteAsync with TimeSpan? timeout on every call |
| Device identity | COM port number (unstable across re-plug) | Device interface path (stable, unique, assigned by OS) |
| Event model | DataReceived fires on a threadpool thread with no backpressure; easy to miss data or deadlock |
Pull-based async reads — caller controls the read loop and timing |
| USB CDC | Requires manual baud/parity configuration even though CDC ignores it | Works out of the box — no PortSettings needed for CDC devices |
Windows HID devices don't need a kernel driver — the OS provides one automatically — but communicating with them still requires juggling hid.dll for metadata, kernel32.dll for I/O, overlapped structures for async, CancelIoEx for timeouts, and careful handle lifecycle. Anp.Usb.Hid.Win32 wraps all of that into a simple open/read/write/close API with:
- Device disconnect handled cleanly —
HidDisconnectedExceptionon the calling thread, not a corrupted handle - Per-call timeouts — no need to manage your own
OVERLAPPED+WaitForSingleObject+CancelIoExdance - Discovery and hot-plug — find devices by VID/PID, get notified on arrival/removal
- Report abstraction — work with
HidReport(report ID + data) or raw byte arrays
| Package | Transport | Typical Devices |
|---|---|---|
| COM port (USB CDC, USB-to-serial, RS232, Bluetooth) | Arduino (CDC), GPS modules, barcode scanners, FTDI/CH340/CP2102 adapters | |
| USB HID | Custom HID devices, bootloaders, digital scales, LED controllers, relay boards |
Both libraries share a common design:
- Discovery — enumerate devices by interface GUID, optionally filtered by USB VID/PID
- Hot-plug monitoring — real-time device arrival/removal notifications (Windows 8+)
- Async I/O with per-call timeouts — every read/write accepts a
TimeSpan? timeout(default 2 s) - Graceful disconnect handling — mid-I/O device removal throws a typed exception, not corruption
- Subclassable —
OnOpened()/OnClosing()hooks for protocol init and teardown - Diagnostics — subscribe to library-level error events for logging and troubleshooting
- Zero mandatory NuGet dependencies on .NET Framework 4.8 — only Windows system DLLs via P/Invoke
using Anp.Serial.Win32;
var devices = SerialDiscovery.GetDevices(vendorId: 0x2341); // Arduino
using (var device = devices[0])
{
device.Open();
await device.WriteLineAsync("HELLO");
string response = await device.ReadLineAsync(timeout: TimeSpan.FromSeconds(5));
Console.WriteLine(response);
device.Close();
}using Anp.Usb.Hid.Win32;
var devices = HidDiscovery.GetDevices(vendorId: 0x1234, productId: 0x0001);
using (var device = devices[0])
{
device.Open();
await device.WriteOutputReportAsync(new HidReport(0x00, new byte[] { 0x01, 0x02 }));
HidReport report = await device.ReadInputReportAsync(timeout: TimeSpan.FromSeconds(5));
Console.WriteLine(BitConverter.ToString(report.Data));
device.Close();
}Runnable sample projects are in the samples/ directory:
| Sample | Description |
|---|---|
| Serial.BasicDiscovery | Enumerate devices, print metadata |
| Serial.ReadWrite | Open, write, read (CDC and adapter patterns) |
| Serial.HotPlug | Monitor device arrival/removal in real time |
| Serial.LiveMonitor | Continuous read loop with infinite timeout |
| Serial.DerivedDevice | Subclass with protocol hooks |
| Hid.BasicDiscovery | Enumerate HID devices, print metadata |
| Hid.ReadWrite | Open, write/read reports |
| Hid.HotPlug | Monitor HID device arrival/removal |
| Hid.LiveMonitor | Continuous report read loop |
| Hid.DerivedDevice | Subclass with protocol hooks |
- .NET Framework 4.8, .NET Standard 2.0, or .NET 8+ (Windows)
- Windows Vista or later (discovery and I/O)
- Windows 8 or later (hot-plug monitoring)
src/
Serial.Win32/ COM port serial device library
Usb.Hid.Win32/ USB HID device library
Devices.Win32.Core/ Shared project (compiled into both libraries)
samples/
Serial.*/ Serial sample projects
Hid.*/ HID sample projects
- PnpDeviceToolkit — external device discovery and enumeration tool; device paths from PnpDeviceToolkit can be used directly with
SerialDeviceandHidDeviceconstructors.