using System; using System.Collections.Generic; using System.IO.Ports; using System.Linq; using System.Timers; public sealed class SerialPortWatcher : IDisposable { private readonly System.Timers.Timer _timer; private HashSet _last = new(StringComparer.OrdinalIgnoreCase); public event Action? PortsAdded; public event Action? PortsRemoved; public SerialPortWatcher(double intervalMs = 1000) { _timer = new System.Timers.Timer(intervalMs); _timer.Elapsed += (_, _) => Tick(); _timer.AutoReset = true; } public void Start() { _last = GetPorts(); _timer.Start(); } public void Stop() => _timer.Stop(); private void Tick() { var current = GetPorts(); var added = current.Except(_last).ToArray(); var removed = _last.Except(current).ToArray(); if (added.Length > 0) PortsAdded?.Invoke(added); if (removed.Length > 0) PortsRemoved?.Invoke(removed); _last = current; } private static HashSet GetPorts() => new HashSet(SerialPort.GetPortNames(), StringComparer.OrdinalIgnoreCase); public void Dispose() { _timer.Stop(); _timer.Dispose(); } }