How do I get a list of available serial ports in Win32?

后端 未结 5 1632
青春惊慌失措
青春惊慌失措 2020-11-29 19:16

I have some legacy code that provides a list of the available COM ports on the PC by calling the EnumPorts() function and then filtering for the port names that start with \

相关标签:
5条回答
  • 2020-11-29 19:30

    It appears that it's not a simple task.

    Check out this: EnumSerialPorts v1.20

    0 讨论(0)
  • 2020-11-29 19:33

    The EnumSerialPorts v1.20 suggested by Nick D uses nine different methods to list the serial ports! We're certainly not short on choice, though the results seem to vary.

    To save others the trouble, I'll list them here and indicate their success in finding the com0com ports on my PC (XP Pro SP2):

    1. CreateFile("COM" + 1->255) as suggested by Wael Dalloul
      ✔ Found com0com ports, took 234ms.

    2. QueryDosDevice()
      ✔ Found com0com ports, took 0ms.

    3. GetDefaultCommConfig("COM" + 1->255)
      ✔ Found com0com ports, took 235ms.

    4. "SetupAPI1" using calls to SETUPAPI.DLL
      ✔ Found com0com ports, also reported "friendly names", took 15ms.

    5. "SetupAPI2" using calls to SETUPAPI.DLL
      ✘ Did not find com0com ports, reported "friendly names", took 32ms.

    6. EnumPorts()
      ✘ Reported some non-COM ports, did not find com0com ports, took 15ms.

    7. Using WMI calls
      ✔ Found com0com ports, also reported "friendly names", took 47ms.

    8. COM Database using calls to MSPORTS.DLL
      ✔/✘ Reported some non-COM ports, found com0com ports, took 16ms.

    9. Iterate over registry key HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM
      ✔ Found com0com ports, took 0ms. This is apparently what SysInternals PortMon uses.

    Based on those results I think the WMI method probably suits my requirements best as it is relatively fast and as a bonus it also gives the friendly names (e.g. "Communications Port (COM1)", "com0com - serial port emulator").

    0 讨论(0)
  • 2020-11-29 19:43

    In my case, I need both the full names, and COM port addresses. I have physical serial ports, USB serial ports, and com0com virtual serial ports.

    Like the accepted answer suggests, I use WMI calls. SELECT * FROM Win32_PnPEntity find all devices. It returns physical devices like this, and address can be parsed from Caption:

    Serial Port for Barcode Scanner (COM13)
    

    However, for com0com ports Caption is like this (no address):

    com0com - serial port emulator
    

    SELECT * FROM Win32_SerialPort returns addresses (DeviceID), as well as full names (Name). However, it only finds physical serial ports and com0com ports, not USB serial ports.

    So in the end, I need two WMI calls: SELECT * FROM Win32_SerialPort (address is DeviceID) and SELECT * FROM Win32_PnPEntity WHERE Name LIKE '%(COM%' (address can be parsed from Caption). I have narrowed down the Win32_PnPEntity call, because it only needs to find devices that were not found in the first call.

    0 讨论(0)
  • 2020-11-29 19:46

    you can make loop for example from 1 to 50 and try to open each port. If the port is available, the open will work. If the port is in use, you'll get a sharing error. If the port is not installed, you'll get a file not found error.

    to open the port use CreateFile API:

    HANDLE Port = CreateFile(
                      "\\\\.\\COM1",
                      GENERIC_READ | GENERIC_WRITE,
                      0,
                      NULL,
                      OPEN_EXISTING,
                      FILE_ATTRIBUTE_NORMAL,
                      NULL);
    

    then check the result.

    0 讨论(0)
  • 2020-11-29 19:50

    I have reorganized PJ Naughter 's EnumSerialPorts as more portable and individual forms, that is more useful.

    For better in compatibility, I use C, instead of C++.

    If you need or be interested in it, please visit the post in my blogger.

    0 讨论(0)
提交回复
热议问题