Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

New COM port available event

My C# application uses the COM ports. I am having some difficulty that should be common to most programs. I need to get an event when the list of Portnames changes. I have a selection box where the user can choose from teh list of available port names. Does anyone have a snippet of code for this? Thank You.

like image 808
user1389312 Avatar asked May 11 '12 11:05

user1389312


People also ask

How do I find out what COM ports are available?

1) Click Start. 2) Click Control Panel in the Start menu. 3) Click Device Manager in the Control Panel. 4) Click + next to Port in the Device Manager to display the port list.


2 Answers

It can also be done with help of "ManagementEventWatcher":

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Management;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;

namespace HmxFlashLoader
{
    /// <summary>
    /// Make sure you create this watcher in the UI thread if you are using the com port list in the UI
    /// </summary>
    [Export]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public sealed class SerialPortWatcher : IDisposable
    {
        public SerialPortWatcher()
        {
            _taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
            ComPorts = new ObservableCollection<string>(SerialPort.GetPortNames().OrderBy(s => s));

            WqlEventQuery query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent");

            _watcher = new ManagementEventWatcher(query);           
            _watcher.EventArrived += (sender, eventArgs) => CheckForNewPorts(eventArgs);
            _watcher.Start();       
        }

        private void CheckForNewPorts(EventArrivedEventArgs args)
        {
            // do it async so it is performed in the UI thread if this class has been created in the UI thread
            Task.Factory.StartNew(CheckForNewPortsAsync, CancellationToken.None, TaskCreationOptions.None, _taskScheduler);
        }

        private void CheckForNewPortsAsync()
        {
            IEnumerable<string> ports = SerialPort.GetPortNames().OrderBy(s => s);

            foreach (string comPort in ComPorts)
            {
                if (!ports.Contains(comPort))
                {
                    ComPorts.Remove(comPort);
                }
            }

            foreach (var port in ports)
            {           
                if (!ComPorts.Contains(port))
                {
                    AddPort(port);
                }
            }
        }

        private void AddPort(string port)
        {
            for (int j = 0; j < ComPorts.Count; j++)
            {
                if (port.CompareTo(ComPorts[j]) < 0)
                {
                    ComPorts.Insert(j, port);
                    break;
                }
            }

        }

        public ObservableCollection<string> ComPorts { get; private set; }

        #region IDisposable Members

        public void Dispose()
        {
            _watcher.Stop();    
        }

        #endregion

        private ManagementEventWatcher _watcher;
        private TaskScheduler _taskScheduler;
    }
}
like image 179
huer12 Avatar answered Sep 28 '22 01:09

huer12


COM ports changing is a rare event, not a common one.

The easiest way would be to have a timer and every 10-30 seconds enumerate the list of COM ports and if changed, update the list.

Better still, provide a "refresh list" button - the list will basically only change if the user has plugged a USB Serial adapter in.

like image 23
Ben Avatar answered Sep 28 '22 00:09

Ben