我正在寻找一种可靠的方式来列出Windows机器上的可用串行(COM)端口。 这里有关于使用WMI的这篇文章 ,但是我想要less一些特定于.NET的东西 – 我想在没有.NET的情况下获取Python或C ++程序中的端口列表。
我目前知道另外两种方法:
读取HARDWARE\\DEVICEMAP\\SERIALCOMM
registry项中的信息。 这看起来像一个很好的select,但它是强大的 ? 我不能在网上或MSDN中find一个保证,这个registry单元确实总是保存可用端口的完整列表。
尝试调用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
有几个选项可用:
用NULL lpDeviceName调用QueryDosDevice来列出所有的DOS设备。 然后使用每个设备名称的CreateFile和GetCommConfig来判断它是否是串口。
使用GUID_DEVINTERFACE_COMPORT的ClassGuid调用SetupDiGetClassDevs。
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()