代码之家  ›  专栏  ›  技术社区  ›  Eli Bendersky

在Windows上列出串行(COM)端口?

  •  28
  • Eli Bendersky  · 技术社区  · 16 年前

    我正在寻找一种可靠的方法来列出Windows机器上可用的串行(COM)端口。有 this post about using WMI 但是我想少一些.NET特定的——我想得到一个Python或C++程序中的端口列表,没有.NET。

    我目前还知道其他两种方法:

    1. 阅读中的信息 HARDWARE\\DEVICEMAP\\SERIALCOMM 注册表项。这看起来是个不错的选择,但它是不是 稳健的 ?我无法在网上或在msdn中找到这样一个保证:这个注册表单元确实始终保存着可用端口的完整列表。

    2. 调用TyIt CreateFile COMN n是从1到某物的数字。这还不够好,因为有些COM端口没有命名为COMN。例如,创建的一些虚拟COM端口名为csna0、csnb0等,因此我不依赖于此方法。

    还有其他方法/想法/经验可以分享吗?

    编辑: 顺便说一下,下面是从注册表中读取端口名的简单python实现:

    import _winreg as winreg
    import itertools
    
    
    def enumerate_serial_ports():
        """ Uses the Win32 registry to return a iterator of serial 
            (COM) ports existing on this computer.
    
    
        """
        path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
        try:
            key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path)
        except WindowsError:
            raise IterationError
    
        for i in itertools.count():
            try:
                val = winreg.EnumValue(key, i)
                yield (str(val[1]), str(val[0]))
            except EnvironmentError:
                break
    
    8 回复  |  直到 7 年前
        1
  •  7
  •   Oren Trutner    16 年前

    有几种选择:

    1. 呼叫 QueryDosDevice 用空的lpdevicename列出所有DOS设备。然后使用createfile和 GetCommConfig 依次使用每个设备名来确定它是否是串行端口。

    2. 呼叫 SetupDiGetClassDevs 具有guid_devinterface_comport的classguid。

    3. WMI is also available to C/C++ programs .

    有一些关于 win32 newsgroup 还有一个代码项目,呃, project .

        2
  •  31
  •   Matt Williams    11 年前

    使用pyserial和python:

    import serial.tools.list_ports
    
    
    ports = list(serial.tools.list_ports.comports())
    for p in ports:
        print p
    
        3
  •  6
  •   Rainald62    7 年前

    pyserial项目提供 couple of solutions .

        4
  •  5
  •   tomlogic    15 年前

    我刚刚创建了以下内容,基于C++源代码的读取 EnumSerialPorts 看到了功能 GetDefaultCommConfig() .对于每个可能的COM端口,使用简单的ANSIC和一个API调用看起来是最简单的方法。

    #include <stdio.h>
    #include <windows.h>
    #include <winbase.h>
    
    BOOL COM_exists( int port)
    {
        char buffer[7];
        COMMCONFIG CommConfig;
        DWORD size;
    
        if (! (1 <= port && port <= 255))
        {
            return FALSE;
        }
    
        snprintf( buffer, sizeof buffer, "COM%d", port);
        size = sizeof CommConfig;
    
        // COM port exists if GetDefaultCommConfig returns TRUE
        // or changes <size> to indicate COMMCONFIG buffer too small.
        return (GetDefaultCommConfig( buffer, &CommConfig, &size)
                                                        || size > sizeof CommConfig);
    }
    
    int main()
    {
        int i;
    
        for (i = 1; i < 256; ++i)
        {
            if (COM_exists( i))
            {
                printf( "COM%d exists\n", i);
            }
        }
    
        return 0;
    }
    
        5
  •  3
  •   eatonphil    12 年前

    这肯定是相当晚了,但事实证明它对我有帮助!

    http://eli.thegreenplace.net/2009/07/31/listing-all-serial-ports-on-windows-with-python/

    尤其是这个例子:

    import re
    
    def full_port_name(portname):
        """ Given a port-name (of the form COM7,
            COM12, CNCA0, etc.) returns a full
            name suitable for opening with the
            Serial class.
        """
        m = re.match('^COM(\d+)$', portname)
        if m and int(m.group(1)) < 10:
        return portname
    return '\\\\.\\' + portname
    
        6
  •  2
  •   Ben    13 年前

    在pyserial发行版中有一个例子,叫做scanwin32.py。

    http://pyserial.sourcearchive.com/documentation/2.5/scanwin32_8py_source.html

        7
  •  2
  •   Pithikos    10 年前

    我认为wmi是一种可行的方法,因为它非常容易实现,而且它只有最少的代码。它可以避免你在注册表中进行挖掘,并为你提供一些保证,使你将来可以在更一般的情况下使用它。

    您可以安装所需的一切 pip install pypiwin32 WMI 它是开箱即用的。

    代码

    import wmi
    
    query = "SELECT * FROM Win32_PnPEntity WHERE Name LIKE '%(COM%)'"
    coms  = wmi.WMI().query(query)
    
    for com in coms:
        print(com.Name)
    

    产量

    Communications Port (COM1)
    mbed Serial Port (COM3)
    mbed Serial Port (COM5)
    

    我猜您的串行端口是某种即插即用的,所以这应该可以正常工作。出于某种原因 Win32_SerialPort 不适用于所有端口。

        8
  •  2
  •   Paul Williams    10 年前

    现在有一个PowerShell一行程序。

    [System.IO.Ports.SerialPort]::GetPortNames()