1

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();
            
        }
mrkefca
  • 55
  • 8

3 Answers3

0

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"]);
    }
d4zed
  • 478
  • 2
  • 6
  • 16
  • Querying Win32_DiskDrive is unlikely to be useful. – Hans Passant Feb 03 '23 at 11:08
  • with string[] ports = SerialPort.GetPortNames(); I get 3 com port listed but with your code I get info only for 2 serial ports listed. Any idea why ? 2 devices have locaition USB serial connection, one have location Port_#0005.Hub_#0001. All 3 devices are recognized as COM ports, but ony 2 are recognized with your code. – mrkefca Feb 03 '23 at 12:17
  • also next to the device id, must be addet com port number – mrkefca Feb 03 '23 at 12:41
  • @mrkefca: You might be dealing with counterfeit hardware. It looks like your 3 com ports only have 2 serial numbers. `A104M1Q0` appears twice. – MSalters Feb 03 '23 at 15:35
  • @MSalters I manually add this text to com port only for example. Every COM device has its own SN. Changing Win32_USBHub2 with Win32_PnPEntity fix the problem. – mrkefca Feb 06 '23 at 07:17
0

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';
    }
}

0

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
-----------------------------------
mrkefca
  • 55
  • 8