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

我正在寻找一种可靠的方式来列出Windows机器上的可用串行(COM)端口。 这里有关于使用WMI的这篇文章 ,但是我想要less一些特定于.NET的东西 – 我想在没有.NET的情况下获取Python或C ++程序中的端口列表。

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

  1. 读取HARDWARE\\DEVICEMAP\\SERIALCOMMregistry项中的信息。 这看起来像一个很好的select,但它是强大的 ? 我不能在网上或MSDN中find一个保证,这个registry单元确实总是保存可用端口的完整列表。

  2. 尝试调用COMN CreateFile N从1到某个数字。 这不够好,因为一些COM端口没有被命名为COMN。 例如,一些创build的虚拟COM端口被命名为CSNA0,CSNB0等等,所以我不会依赖这个方法。

任何其他方法/想法/经验分享?

编辑:顺便说一下,这是一个简单的Python实现从registry读取端口名称:

 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 

有几个选项可用:

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

  2. 使用GUID_DEVINTERFACE_COMPORT的ClassGuid调用SetupDiGetClassDevs。

  3. WMI也可用于C / C ++程序 。

在win32新闻组和一个CodeProject呃项目上有一些对话。

在Python中使用pySerial:

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

我只是通过读取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; } 

PySerial项目提供了一些解决方案 。

这绝对是相当晚,但它对我有帮助!

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 

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

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

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

现在有一个Powershell单线程的。

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