Skip to content

Instantly share code, notes, and snippets.

@M0n7y5
Created January 9, 2019 14:20
Show Gist options
  • Save M0n7y5/b45669c238ff3f2602c1859b3829137c to your computer and use it in GitHub Desktop.
Save M0n7y5/b45669c238ff3f2602c1859b3829137c to your computer and use it in GitHub Desktop.
Elegant Serial Port Connect / Disconnect Detection using WMI and C#
using System;
using System.Management;
namespace WMITester
{
class Program
{
static void Main(string[] args)
{
try
{
// I ended up using MSSerial_PortName from root\WMI, because Win32_SerialPort from root\CIMV2 won't detect my FTDI Serial Converter
// (but it's showed up properly in Device manager) and it's also firing multiple events per device disconnecting/connecting
// more info here https://stackoverflow.com/questions/19840811/list-of-serialports-queried-using-wmi-differs-from-devicemanager
ManagementScope managementScope = new ManagementScope(@"root\WMI");
// Declaring queries for creation and deletion events of MSSerial_PortName instances
// we want pull query every 1 second so we get small latency between
WqlEventQuery creatonQuery = new WqlEventQuery("__InstanceCreationEvent", TimeSpan.FromSeconds(1),
"TargetInstance ISA 'MSSerial_PortName'");
WqlEventQuery deletionQuery = new WqlEventQuery("__InstanceDeletionEvent", TimeSpan.FromSeconds(1),
"TargetInstance ISA 'MSSerial_PortName'");
// Initalize ManagementEventWatchers each for attach and detach
ManagementEventWatcher deviceAttachWatcher = new ManagementEventWatcher(managementScope, creatonQuery);
ManagementEventWatcher deviceDetachWatcher = new ManagementEventWatcher(managementScope, deletionQuery);
Console.WriteLine("Waiting for an events...");
// Event handlers
deviceAttachWatcher.EventArrived += deviceAttachWatcher_EventArrived;
deviceDetachWatcher.EventArrived += DeviceDetachWatcher_EventArrived;
// Connect to our scope
managementScope.Connect();
// Start listening for events
deviceAttachWatcher.Start();
deviceDetachWatcher.Start();
}
catch( Exception ex)
{
Console.WriteLine(ex);
}
while (true) { }
}
private static void DeviceDetachWatcher_EventArrived(object sender, EventArrivedEventArgs e)
{
// Get instance of MSSerial_PortName class
// More info about that class http://wutils.com/wmi/root/wmi/msserial_portname/
var instance = e.NewEvent.GetPropertyValue("TargetInstance") as ManagementBaseObject;
// Now we are ready to access properties of MSSerial_PortName itself
Console.WriteLine($"Port: {instance.GetPropertyValue("PortName")} disconnected!");
}
private static void deviceAttachWatcher_EventArrived(object sender, EventArrivedEventArgs e)
{
// Get instance of MSSerial_PortName
var instance = e.NewEvent.GetPropertyValue("TargetInstance") as ManagementBaseObject;
// Now we are ready to access properties of MSSerial_PortName itself
Console.WriteLine($"Port: {instance.GetPropertyValue("PortName")} connected!");
}
}
}
@rprimora
Copy link

rprimora commented Nov 2, 2021

This will not work if no COM port was connected prior to application execution. The code will throw error on first watcher Start() method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment