列出Windows上的串行(COM)端口?
-
05-07-2019 - |
题
我正在寻找一种强大的方法来列出Windows机器上可用的串行(COM)端口。有这篇关于使用WMI的帖子,但我想要一些特定于.NET的东西 - 我想在没有.NET的情况下获得Python或C ++程序中的端口列表。
我目前知道另外两种方法:
-
读取
HARDWARE \\ DEVICEMAP \\ SERIALCOMM
注册表项中的信息。这看起来是一个很好的选择,但健壮?我无法在线或在MSDN中找到此注册表单元确实始终包含可用端口的完整列表的保证。 -
尝试在
COMN
上调用CreateFile
,其中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
解决方案
有几种选择:
-
致电 QueryDosDevice NULL lpDeviceName列出所有DOS设备。然后在每个设备名称中使用CreateFile和 GetCommConfig 转而弄清楚它是否是一个串口。
-
使用GUID_DEVINTERFACE_COMPORT的ClassGuid调用 SetupDiGetClassDevs 。
- 醇>
其他提示
在Python中使用pySerial:
import serial.tools.list_ports
ports = list(serial.tools.list_ports.comports())
for p in ports:
print p
PySerial项目提供几种解决方案。
我刚刚创建了以下内容,基于阅读C ++源代码来 EnumSerialPorts 并查看function 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;
}
这肯定是相当晚的,但事实证明这对我有帮助!
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()