com port identification by device serial number

1.2k Views Asked by At

In our company for testing purposes, we use many serial COM port devices. These devices are transferred daily between several PC and whenever we add a new serial device, we have to manualy learn on all computers.

Currently I am working on code, for automatic COM port device detection. My question is, how to list also device ID in c++ or c# next to the active COM port list?

enter image description here

With serial number, I will be able to automatically detect on what port device is on on each PC. Also for FTDI, Silicon Labs,..USB to RS232 converter I can manualy set device SN. Solution need to work on windows 7 or newer.

For example:

![enter image description here

My code:

       static void Main(string[] args)
        {

            // Get a list of serial port names.
            string[] ports = SerialPort.GetPortNames();

            Console.WriteLine("The following serial ports were found:");

            // Display each port name to the console.
            foreach (string port in ports)
            {
                Console.WriteLine(port);
            }

            Console.ReadLine();
            
        }
3

There are 3 best solutions below

0
mrkefca On BEST ANSWER

I found a working code check this post Getting Serial Port Information

Code:

using System.Management;
using Microsoft.Win32;

using (ManagementClass i_Entity = new ManagementClass("Win32_PnPEntity"))
{
    foreach (ManagementObject i_Inst in i_Entity.GetInstances())
    {
        Object o_Guid = i_Inst.GetPropertyValue("ClassGuid");
        if (o_Guid == null || o_Guid.ToString().ToUpper() != "{4D36E978-E325-11CE-BFC1-08002BE10318}")
            continue; // Skip all devices except device class "PORTS"

        String s_Caption  = i_Inst.GetPropertyValue("Caption")     .ToString();
        String s_Manufact = i_Inst.GetPropertyValue("Manufacturer").ToString();
        String s_DeviceID = i_Inst.GetPropertyValue("PnpDeviceID") .ToString();
        String s_RegPath  = "HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Enum\\" + s_DeviceID + "\\Device Parameters";
        String s_PortName = Registry.GetValue(s_RegPath, "PortName", "").ToString();

        int s32_Pos = s_Caption.IndexOf(" (COM");
        if (s32_Pos > 0) // remove COM port from description
            s_Caption = s_Caption.Substring(0, s32_Pos);

        Console.WriteLine("Port Name:    " + s_PortName);
        Console.WriteLine("Description:  " + s_Caption);
        Console.WriteLine("Manufacturer: " + s_Manufact);
        Console.WriteLine("Device ID:    " + s_DeviceID);
        Console.WriteLine("-----------------------------------");
    }
    Console.ReadLine();
}

Console output:

Port Name:    COM29
Description:  CDC Interface (Virtual COM Port) for USB Debug
Manufacturer: GHI Electronics, LLC
Device ID:    USB\VID_1B9F&PID_F003&MI_01\6&3009671A&0&0001
-----------------------------------
Port Name:    COM28
Description:  Teensy USB Serial
Manufacturer: PJRC.COM, LLC.
Device ID:    USB\VID_16C0&PID_0483\1256310
-----------------------------------
Port Name:    COM25
Description:  USB-SERIAL CH340
Manufacturer: wch.cn
Device ID:    USB\VID_1A86&PID_7523\5&2499667D&0&3
-----------------------------------
Port Name:    COM26
Description:  Prolific USB-to-Serial Comm Port
Manufacturer: Prolific
Device ID:    USB\VID_067B&PID_2303\5&2499667D&0&4
-----------------------------------
Port Name:    COM1
Description:  Comunications Port
Manufacturer: (Standard port types)
Device ID:    ACPI\PNP0501\1
-----------------------------------
Port Name:    COM999
Description:  EPSON TM Virtual Port Driver
Manufacturer: EPSON
Device ID:    ROOT\PORTS\0000
-----------------------------------
Port Name:    COM20
Description:  EPSON COM Emulation USB Port
Manufacturer: EPSON
Device ID:    ROOT\PORTS\0001
-----------------------------------
Port Name:    COM8
Description:  Standard Serial over Bluetooth link
Manufacturer: Microsoft
Device ID:    BTHENUM\{00001101-0000-1000-8000-00805F9B34FB}_LOCALMFG&000F\8&3ADBDF90&0&001DA568988B_C00000000
-----------------------------------
Port Name:    COM9
Description:  Standard Serial over Bluetooth link
Manufacturer: Microsoft
Device ID:    BTHENUM\{00001101-0000-1000-8000-00805F9B34FB}_LOCALMFG&0000\8&3ADBDF90&0&000000000000_00000002
-----------------------------------
Port Name:    COM30
Description:  Arduino Uno
Manufacturer: Arduino LLC (www.arduino.cc)
Device ID:    USB\VID_2341&PID_0001\74132343530351F03132
-----------------------------------
5
d4zed On

You can use ManagementObjectSearcher for this. You'll need to add System.Management as a reference.

using System;
using System.Management; // need to add System.Management to your project references

    ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * From Win32_USBHub");

    foreach (ManagementObject queryObj in searcher.Get())
    {
      Console.WriteLine("USB device");
      Console.WriteLine("Caption: {0}", queryObj["Caption"]);
      Console.WriteLine("Description: {0}", queryObj["Description"]);
      Console.WriteLine("DeviceID: {0}", queryObj["DeviceID"]);
      Console.WriteLine("Name: {0}", queryObj["Name"]);
      Console.WriteLine("PNPDeviceID: {0}", queryObj["PNPDeviceID"]);
    }
0
Christian Halaszovich On

If I understood your questions correctly, the C++ code below should help.

Edit: added support for friendly name (which includes COM number).

On my system I get this result, which seems to match your screenshots:

installed serial devices:
Dev. Id: PCI\VEN_8086&DEV_9D3D&SUBSYS_506D17AA&REV_21\3&11583659&1&B3
friendly name: Intel(R) Active Management Technology - SOL (COM3)

Dev. Id: FTDIBUS\VID_0403+PID_6001+A916RGSAA\0000
friendly name: USB Serial Port (COM4)


device interfaces:
Interface: \\?\PCI#VEN_8086&DEV_9D3D&SUBSYS_506D17AA&REV_21#3&11583659&1&B3#{86e0d1e0-8089-11d0-9ce4-08003e301f73}
Interface: \\?\FTDIBUS#VID_0403+PID_6001+A916RGSAA#0000#{86e0d1e0-8089-11d0-9ce4-08003e301f73}
#include <iostream>
#include <string>
#include <string_view>
#include <vector>
#include <initguid.h>
#include <windows.h>
#include <devpkey.h>
#include <cfgmgr32.h>


auto splitListAsString(const std::wstring_view& s)
{
    std::vector<std::wstring> l;
    for (size_t pos{ 0 }; s.at(pos) != 0;) {
        auto newpos = s.find(L'\0', pos);
        l.emplace_back(s.substr(pos, newpos - pos));
        pos = newpos + 1;
    }

    return l;
}

int main()
{
    wchar_t guid_str[] = L"{4D36E978-E325-11CE-BFC1-08002BE10318}";
    auto propKey{ DEVPKEY_Device_FriendlyName };
    ULONG len{};
    auto res = CM_Get_Device_ID_List_Size(&len, guid_str, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
    if (res != CR_SUCCESS) {
        std::cerr << "error num " << res << " occured\n";
        return -1;
    }
    std::wstring devIds(len,'\0');
    res = CM_Get_Device_ID_ListW(guid_str, devIds.data(), len, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
    std::wcout << L"installed serial devices:\n";
    for (auto& e : splitListAsString(devIds)) {
        std::wcout << L"Dev. Id: " << e << L'\n';
        DEVINST devInst{};
        res = CM_Locate_DevInstW(&devInst, e.data(), CM_LOCATE_DEVNODE_NORMAL);
        if (res != CR_SUCCESS) {
            std::cerr << "error locating device " << res << " occured\n";
            continue;
        }
        DEVPROPTYPE devpropt{};
        CM_Get_DevNode_PropertyW(devInst, &propKey, &devpropt, nullptr, &len, 0);

        if (res!=CR_BUFFER_SMALL && res != CR_SUCCESS) {
            std::cerr << "error " << res << "\n";
            continue;
            //return -1;
        }
        auto buffer = std::make_unique<BYTE[]>(len);
        res = CM_Get_DevNode_PropertyW(devInst, &propKey, &devpropt, buffer.get(), &len, 0);
        if (devpropt == DEVPROP_TYPE_STRING) {
            const auto val = reinterpret_cast<wchar_t*>(buffer.get());
            std::wcout << L"friendly name: " << val << L"\n\n";
        }
    }

    auto guid_comport_interface{ GUID_DEVINTERFACE_COMPORT };
    res = CM_Get_Device_Interface_List_SizeW(&len, &guid_comport_interface, nullptr, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
    if (res != CR_SUCCESS) {
        std::cerr << "error num " << res << " occured\n";
        return -1;
    }
    std::wstring devInterfaces(len, '\0');
    res = CM_Get_Device_Interface_ListW(&guid_comport_interface, nullptr, devInterfaces.data(), len, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
    
    std::wcout << L"\ndevice interfaces:\n";
    for (const auto& e : splitListAsString(devInterfaces)) {
        std::wcout << L"Interface: " << e << '\n';
    }
}