Listing serielle Schnittstelle (COM) Ports auf Windows?
-
05-07-2019 - |
Frage
Ich bin auf der Suche nach einem robusten Weg, um die verfügbaren seriellen Ports (COM) auf einem Windows-Rechner aufzulisten. Es gibt diesen Beitrag zu WMI , aber ich würde etwas weniger .NET spezifische mag - ich mag die Liste der Ports in einem Python oder C ++ Programm erhalten, ohne .NET
.Ich weiß noch zwei weitere Ansätze:
-
, um die Information in dem
HARDWARE\\DEVICEMAP\\SERIALCOMM
Registrierungsschlüssel lesen. Dies sieht aus wie eine gute Option, aber ist es robust ? Ich kann keine Garantie online oder in MSDN feststellen, dass diese Registry-Zelle in der Tat immer die vollständige Liste der verfügbaren Ports hält. -
Tryint
CreateFile
aufCOMN
mit N eine Zahl von 1 bis etwas zu nennen. Das ist nicht gut genug, da einige COM-Ports COMN nicht genannt. Zum Beispiel erstellt einig virtueller COM-Ports CSNA0, CSNB0 genannt, und so weiter, so würde ich nicht auf dieser Methode verlassen.
Jede andere Methoden / Ideen / Erfahrungen zu teilen?
Edit: durch die Art und Weise, hier ist eine einfache Python-Implementierung des Portnamen aus der Registry zu lesen:
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
Lösung
Mehrere Optionen stehen zur Verfügung:
-
Rufen Sie QueryDosDevice mit einem NULL lpDeviceName alle DOS-Geräte aufzulisten. Dann verwenden Sie Create und GetCommConfig mit jedem Gerätenamen in drehen, um herauszufinden, ob es eine serielle Schnittstelle.
-
Rufen Sie SetupDiGetClassDevs mit einem ClassGUID von GUID_DEVINTERFACE_COMPORT.
Es gibt einige Gespräche auf der win32 Newsgroup und ein Codeproject, äh, Projekt .
Andere Tipps
Mit pyserial mit Python:
import serial.tools.list_ports
ports = list(serial.tools.list_ports.comports())
for p in ports:
print p
Das pyserial Projekt bietet eine paar Lösungen .
Ich habe gerade die folgenden, basierend auf das Lesen durch die C ++ Quelle EnumSerialPorts und zu sehen, die Funktion GetDefaultCommConfig()
. Es sah aus wie die einfachste Methode, mit einfachen ANSI C und einen einzigen API-Aufruf für jeden möglich COM-Port.
#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;
}
Dies ist auf jeden Fall ziemlich spät, aber es erwies sich als hilfreich für mich!
http: / /eli.thegreenplace.net/2009/07/31/listing-all-serial-ports-on-windows-with-python/
Besonders dieses Beispiel:
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
Es gibt ein Beispiel in der pyserial Distro jetzt, tut dies genannt scanwin32.py
http://pyserial.sourcearchive.com/documentation/2.5/scanwin32_8py_source.html
Ich denke, WMI ist der Weg zu gehen, da es ziemlich einfach ist, in Gang zu bringen, und es hat nur minimalen Code. Es erspart Ihnen, in der Registry zu graben und gibt Ihnen eine Garantie, dass es für allgemeinere Situationen in der Zukunft funktionieren wird.
Sie können alles installieren mit pip install pypiwin32 WMI
benötigt und es funktioniert out-of-the-box.
Code
import wmi
query = "SELECT * FROM Win32_PnPEntity WHERE Name LIKE '%(COM%)'"
coms = wmi.WMI().query(query)
for com in coms:
print(com.Name)
Output
Communications Port (COM1)
mbed Serial Port (COM3)
mbed Serial Port (COM5)
Meine Vermutung ist, dass der Port eine Art Plug ‚n Play so sollte das hervorragend funktionieren. Aus irgendeinem Grund Win32_SerialPort
nicht für alle Ports arbeiten.
Heute gibt es eine Powershell Einzeiler dafür.
[System.IO.Ports.SerialPort]::GetPortNames()