Список последовательных (COM) портов в Windows?
-
05-07-2019 - |
Вопрос
Я ищу надежный способ перечислить доступные последовательные (COM) порты на компьютере с Windows.Там есть этот пост об использовании WMI, но я хотел бы что-то менее специфичное для .NET - я хочу получить список портов в программе на Python или C ++, без .NET.
В настоящее время я знаю о двух других подходах:
Считывание информации, содержащейся в
HARDWARE\\DEVICEMAP\\SERIALCOMM
раздел реестра.Это выглядит как отличный вариант, но так ли это надежный?Я не могу найти гарантию в Интернете или в MSDN, что в этой ячейке реестра действительно всегда содержится полный список доступных портов.Пытаюсь позвонить
CreateFile
вкл .COMN
с 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 с каждым именем устройства в включите, чтобы выяснить, является ли это последовательным портом.
Вызовите SetupDiGetClassDevs с помощью ClassGuid GUID_DEVINTERFACE_COMPORT. р>
В группе новостей win32 есть некоторые разговоры < и CodeProject, т.е. проект .
Другие советы
Использование pySerial с Python:
import serial.tools.list_ports
ports = list(serial.tools.list_ports.comports())
for p in ports:
print p
Проект PySerial предоставляет пару решений .
Я только что создал следующее, основываясь на чтении исходного кода C ++ на EnumSerialPorts и просмотре функция GetDefaultCommConfig ()
. Это выглядело как самый простой метод с использованием простого ANSI C и одного вызова API для каждого возможного COM-порта.
#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)
Я предполагаю, что ваш последовательный порт - это что-то вроде Plug 'n Play, так что это должно работать нормально.По какой - то причине Win32_SerialPort
работает не для всех портов.
В настоящее время для этого есть однострочник Powershell.
[System.IO.Ports.SerialPort]::GetPortNames()