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

时间:2009-07-30 09:08:23

标签: python c windows winapi serial-port

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

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

  1. 读取HARDWARE\\DEVICEMAP\\SERIALCOMM注册表项中的信息。这看起来是一个很好的选择,但健壮?我无法在线或在MSDN中找到此注册表单元确实始终包含可用端口的完整列表的保证。

  2. 尝试在CreateFile上呼叫COMN,其中N为1到某个数字。这还不够好,因为某些COM端口未命名为COMN。例如,创建的一些虚拟COM端口名为CSNA0,CSNB0等,因此我不会依赖此方法。

  3. 要分享的其他方法/想法/经验吗?

    编辑:顺便说一下,这是一个从注册表中读取端口名称的简单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 个答案:

答案 0 :(得分:31)

在Python中使用pySerial:

import serial.tools.list_ports


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

答案 1 :(得分:7)

有几种选择:

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

  2. 使用GUID_DEVINTERFACE_COMPORT的ClassGuid调用SetupDiGetClassDevs

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

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

答案 2 :(得分:6)

PySerial项目提供couple of solutions

答案 3 :(得分:5)

我刚刚创建了以下内容,基于将C ++源代码读入EnumSerialPorts并查看函数GetDefaultCommConfig()。对于每个可能的COM端口,它看起来像是使用简单ANSI C和单个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;
}

答案 4 :(得分:3)

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

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

答案 5 :(得分:2)

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

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

答案 6 :(得分:2)

我认为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)

我的猜测是你的串口是某种Plug&#39; n Play,所以这应该可以正常工作。出于某种原因,Win32_SerialPort并不适用于所有端口。

答案 7 :(得分:2)

现在有一个Powershell单线程。

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