【问题标题】:Listing serial (COM) ports on Windows?在 Windows 上列出串行 (COM) 端口?
【发布时间】:2010-11-15 09:04:21
【问题描述】:

我正在寻找一种可靠的方法来列出 Windows 机器上的可用串行 (COM) 端口。有 this post about using WMI,但我想要一些不那么特定于 .NET 的东西 - 我想在没有 .NET 的情况下获取 Python 或 C++ 程序中的端口列表。

我目前知道另外两种方法:

  1. 读取HARDWARE\\DEVICEMAP\\SERIALCOMM 注册表项中的信息。这看起来是个不错的选择,但它是否强大?我无法在网上或 MSDN 中找到此注册表单元确实始终包含可用端口的完整列表的保证。

  2. 尝试在COMN 上调用CreateFile,并使用从1 到某个数字的N。这还不够好,因为某些 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

【问题讨论】:

  • 看起来对查找 com 端口非常有用 - 我将尝试使用它来查找 Arduino 端口

标签: python c windows winapi serial-port


【解决方案1】:

在 Python 中使用 pySerial:

import serial.tools.list_ports


ports = list(serial.tools.list_ports.comports())
for p in ports:
    print p

【讨论】:

  • 或直接从命令行,python -m serial.tools.list_ports
  • 确保在 p 周围加上括号
【解决方案2】:

有多种选择:

  1. 使用 NULL lpDeviceName 调用 QueryDosDevice 以列出所有 DOS 设备。然后依次使用 CreateFile 和GetCommConfig 与每个设备名称来判断它是否是串口。

  2. 使用 GUID_DEVINTERFACE_COMPORT 的 ClassGuid 调用 SetupDiGetClassDevs

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

win32 newsgroup 和 CodeProject 上有一些对话,呃,project

【讨论】:

  • 尝试使用QueryDosDevice,但无法知道哪些设备是串口。出于某种原因,GetCommConfig 不是 Pywin32 的一部分
  • Teraterm 列出串行端口的能力给我留下了深刻的印象。我查看了源代码,原来ttcmn.c中的ListupSerialPort()指的是that CodeProject project
【解决方案3】:

PySerial 项目提供couple of solutions

【讨论】:

  • 这是 Pyserial 的一个相对较新的功能,但应该是未来的正确解决方案。
【解决方案4】:

我刚刚创建了以下内容,基于阅读 EnumSerialPorts 的 C++ 源代码并查看函数 GetDefaultCommConfig()。它看起来是最简单的方法,使用简单的 ANSI C 并为每个可能的 COM 端口调用一个 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】:

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

    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】:

    现在有一个 Powershell 单行代码。

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

    【讨论】:

      【解决方案7】:

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

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

      【讨论】:

        【解决方案8】:

        我认为 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 不适用于所有端口。

        【讨论】:

          猜你喜欢
          • 2012-08-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-25
          • 2010-12-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多