Domanda

Sto cercando un modo affidabile per elencare le porte seriali (COM) disponibili su un computer Windows. C'è questo post sull'uso di WMI , ma vorrei qualcosa di meno specifico di .NET - Voglio ottenere l'elenco delle porte in un programma Python o C ++, senza .NET.

Attualmente conosco altri due approcci:

  1. Lettura delle informazioni nella chiave di registro HARDWARE \\ DEVICEMAP \\ SERIALCOMM . Sembra un'ottima opzione, ma è robusto ? Non riesco a trovare una garanzia online o in MSDN che questa cella di registro contenga sempre l'elenco completo delle porte disponibili.

  2. Prova a chiamare CreateFile su COMN con N un numero compreso tra 1 e qualcosa. Questo non è abbastanza buono, perché alcune porte COM non sono nominate COMN. Ad esempio, alcune porte COM virtuali create sono denominate CSNA0, CSNB0 e così via, quindi non mi affiderei a questo metodo.

Altri metodi / idee / esperienze da condividere?

Modifica: a proposito, ecco una semplice implementazione di Python per leggere i nomi delle porte dal registro:

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
È stato utile?

Soluzione

Sono disponibili diverse opzioni:

  1. Chiama QueryDosDevice con un NULL lpDeviceName per elencare tutti i dispositivi DOS. Quindi utilizzare CreateFile e GetCommConfig con ciascun nome di dispositivo in girare per capire se si tratta di una porta seriale.

  2. Chiama SetupDiGetClassDevs con un ClassGuid di GUID_DEVINTERFACE_COMPORT.

  3. WMI è disponibile anche per C / C ++ programmi .

C'è qualche conversazione sul win32 newsgroup e un CodeProject, ehm, project .

Altri suggerimenti

Uso di pySerial con Python:

import serial.tools.list_ports


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

Il progetto PySerial fornisce una un paio di soluzioni .

Ho appena creato quanto segue, basandomi sulla lettura del sorgente C ++ su EnumSerialPorts e vedendo il funzione GetDefaultCommConfig () . Sembrava il metodo più semplice usando ANSI C semplice e una singola chiamata API per ogni possibile porta 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;
}

Questo è decisamente abbastanza tardi, ma mi è stato utile!

http: / /eli.thegreenplace.net/2009/07/31/listing-all-serial-ports-on-windows-with-python/

In particolare questo esempio:

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

Ora c'è un esempio nella distro pyserial che si chiama scanwin32.py

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

Penso che WMI sia la strada da percorrere poiché è abbastanza facile iniziare e ha un codice minimo. Ti evita di dover scavare nel registro e ti dà la garanzia che funzionerà per situazioni più generali in futuro.

Puoi installare tutto il necessario con pip install pypiwin32 WMI e funziona subito.

Codice

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)

La mia ipotesi è che la tua porta seriale sia una sorta di Plug 'n Play, quindi dovrebbe funzionare bene. Per qualche motivo Win32_SerialPort non funziona per tutte le porte.

Oggi c'è un one-liner Powershell per questo.

[System.IO.Ports.SerialPort]::GetPortNames()
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top