Skip to content

Commit

Permalink
- improve serial port names & descriptions using WMI
Browse files Browse the repository at this point in the history
 - add context menu showing current serial ports
  • Loading branch information
alk0ve committed Jun 9, 2020
1 parent d317509 commit c87fbf9
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 17 deletions.
3 changes: 2 additions & 1 deletion Console/Program.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Threading;
using System.Management;
using shared;

namespace TestConsole
Expand All @@ -20,7 +21,7 @@ static void Main(string[] args)

if (!Enumerable.SequenceEqual(older_ports, newer_ports))
{
Console.Write(Serial.GetDiff(older_ports, newer_ports));
Console.Write(Serial.FormatDiff(older_ports, newer_ports));
}

older_ports = newer_ports;
Expand Down
1 change: 1 addition & 0 deletions Console/TestConsole.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Management" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
SerialPop is a tiny C# system tray app that shows pop-ups when serial ports are connected or disconnected to/from the machine.
SerialPop is a tiny C# system tray app that shows pop-ups when serial ports are connected or disconnected to/from the machine.

USAGE:
1) Run SerialPop.exe, it will appear in your system tray
1.1) It's a good idea to configure the taskbar to always show it
1.2) Another good idea would be to have it run during startup

2) Whenever a serial port appears or disappears you'll get a toast notification with the details

3) Right-click on the taskbar icons to see all the currently connected serial ports
2 changes: 1 addition & 1 deletion SerialPop/CustomApplicationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ private void InitializeContext()
components = new System.ComponentModel.Container();
notifyIcon = new NotifyIcon(components)
{
//ContextMenuStrip = new ContextMenuStrip(),
ContextMenuStrip = new ContextMenuStrip(),
Icon = new Icon(IconFileName),
Text = DefaultTooltip,
Visible = true
Expand Down
83 changes: 74 additions & 9 deletions SerialPop/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,98 @@
using System.Threading;
using System.Linq;
using shared;
using System.Collections.Generic;

namespace SerialPop
{
static class Program
{

static void UpdateContextMenu(ContextMenuStrip strip, IOrderedEnumerable<string> newer_ports)
{
strip.Close();
strip.Items.Clear();
foreach (string new_port in newer_ports)
{
strip.Items.Add(new_port);
}
}

static void InvokeUpdateContextMenu(NotifyIcon notifyIcon, IOrderedEnumerable<string> newer_ports)
{
if (notifyIcon.ContextMenuStrip.InvokeRequired)
{
// invoke the update on the UI thread
notifyIcon.ContextMenuStrip.Invoke((MethodInvoker)delegate
{
UpdateContextMenu(notifyIcon.ContextMenuStrip, newer_ports);
});
}
else
{
UpdateContextMenu(notifyIcon.ContextMenuStrip, newer_ports);
}
}

static void PollLoop(object argument)
{
NotifyIcon notifyIcon = (NotifyIcon)argument;

IOrderedEnumerable<string> older_ports = Serial.GetSortedSerialPortNames();
IOrderedEnumerable<string> newer_ports = older_ports;
// GetSortedSerialPortNames() can throw, so initialization has to be trivial
IOrderedEnumerable<string> older_ports = null;
IOrderedEnumerable<string> newer_ports = null;

while (true)

// loop until you get one good WMI query, then initialize everything
while (older_ports == null)
{
try
{
newer_ports = Serial.GetSortedSerialPortNames();
older_ports = newer_ports;

InvokeUpdateContextMenu(notifyIcon, newer_ports);
}
catch (WMIException e)
{
notifyIcon.ShowBalloonTip(5000,
"SerialPop ERROR:",
e.Message,
ToolTipIcon.Error);
}
Thread.Sleep(1000);
}

newer_ports = Serial.GetSortedSerialPortNames();
while (true)
{
try
{
newer_ports = Serial.GetSortedSerialPortNames();

if (!Enumerable.SequenceEqual(older_ports, newer_ports))
{
// the tooltip is limited to 64 characters :(
//notifyIcon.Text = Serial.FormatPortSummary(newer_ports).Substring(0, 63);

InvokeUpdateContextMenu(notifyIcon, newer_ports);

if (!Enumerable.SequenceEqual(older_ports, newer_ports))
notifyIcon.ShowBalloonTip(5000,
"Serial ports changed:",
Serial.FormatDiff(older_ports, newer_ports),
ToolTipIcon.Info);
}

older_ports = newer_ports;
}
catch (WMIException e)
{
notifyIcon.ShowBalloonTip(5000,
"Serial ports changed:",
Serial.GetDiff(older_ports, newer_ports),
ToolTipIcon.Info);
"SerialPop ERROR:",
e.Message,
ToolTipIcon.Error);
}

older_ports = newer_ports;
Thread.Sleep(1000);
}
}

Expand Down
58 changes: 53 additions & 5 deletions shared/serial.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,75 @@
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Management;
using System.Collections;
using System.Collections.Generic;

namespace shared
{
public class WMIException: System.Exception
{
public WMIException()
{ }

public WMIException(string message)
: base(message)
{ }

public WMIException(string message, System.Exception inner)
: base(message, inner)
{ }

}


public class Serial
{
// may throw WMIException
public static IOrderedEnumerable<string> GetSortedSerialPortNames()
{
return SerialPort.GetPortNames().OrderBy(t => t); // returns COM1, COM5, etc.
List<string> portNames = new List<string>();

try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT Caption FROM Win32_PnPEntity where ConfigManagerErrorCode = 0 and PNPClass=\"Ports\"");

foreach (ManagementObject queryObj in searcher.Get())
{
portNames.Add((string)queryObj["Caption"]);
}
}
catch (ManagementException e)
{
throw new WMIException("ERROR while querying WMI: " + e.Message);
}

return portNames.OrderBy(t => t);

}

public static string GetDiff(IOrderedEnumerable<string> old, IOrderedEnumerable<string> newer)
public static string FormatPortSummary(IOrderedEnumerable<string> currentPorts)
{
StringBuilder sb = new StringBuilder();
foreach (string port in currentPorts)
{
sb.AppendLine(port);
}

return sb.ToString();
}

public static string FormatDiff(IOrderedEnumerable<string> old, IOrderedEnumerable<string> newer)
{
StringBuilder sb = new StringBuilder();
foreach (string s in old.Except(newer))
foreach (string s in old.Except(newer))
{
// removed devices
sb.AppendFormat(" - {0}\n", s);
}

foreach (string s in newer.Except(old))
foreach (string s in newer.Except(old))
{
// new devices
sb.AppendFormat(" + {0}\n", s);
Expand Down
1 change: 1 addition & 0 deletions shared/shared.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Management" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
Expand Down

0 comments on commit c87fbf9

Please sign in to comment.