using System; using System.IO.Ports; using System.Linq; using System.Management; namespace Elwig.Helpers { public sealed class SerialPortWatcher : IDisposable { private readonly ManagementEventWatcher _deviceArrivalWatcher; private readonly ManagementEventWatcher _deviceRemovalWatcher; private string[] _knownPorts; public event EventHandler? SerialPortConnected; public event EventHandler? SerialPortDisconnected; public SerialPortWatcher() { _knownPorts = SerialPort.GetPortNames(); _deviceArrivalWatcher = new ManagementEventWatcher("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2"); _deviceArrivalWatcher.EventArrived += (s, e) => OnDeviceArrived(); _deviceRemovalWatcher = new ManagementEventWatcher("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 3"); _deviceRemovalWatcher.EventArrived += (s, e) => OnDeviceRemoved(); _deviceArrivalWatcher.Start(); _deviceRemovalWatcher.Start(); } private void OnDeviceArrived() { string[] currentPorts = SerialPort.GetPortNames(); var newPorts = currentPorts.Except(_knownPorts).ToArray(); foreach (var port in newPorts) SerialPortConnected?.Invoke(this, port); _knownPorts = currentPorts; } private void OnDeviceRemoved() { string[] currentPorts = SerialPort.GetPortNames(); var removedPorts = _knownPorts.Except(currentPorts).ToArray(); foreach (var port in removedPorts) SerialPortDisconnected?.Invoke(this, port); _knownPorts = currentPorts; } public void Dispose() { try { _deviceArrivalWatcher?.Stop(); _deviceRemovalWatcher?.Stop(); } finally { _deviceArrivalWatcher?.Dispose(); _deviceRemovalWatcher?.Dispose(); } } } }