Question

Je recherche un moyen robuste d’énumérer les ports série (COM) disponibles sur une machine Windows. Il existe ce message sur l’utilisation de WMI , mais je voudrais quelque chose de moins spécifique à .NET - Je souhaite obtenir la liste des ports dans un programme Python ou C ++, sans .NET.

Je connais actuellement deux autres approches:

  1. Lecture des informations contenues dans la clé de registre HARDWARE \\ DEVICEMAP \\ SERIALCOMM . Cela semble être une bonne option, mais est-il robuste ? Je ne trouve aucune garantie en ligne ou dans MSDN sur le fait que cette cellule de registre contient toujours la liste complète des ports disponibles.

  2. Essayez d'appeler CreateFile sur COMN avec N un nombre compris entre 1 et quelque chose. Cela ne suffit pas, car certains ports COM ne sont pas nommés COMN. Par exemple, certains ports COM virtuels créés sont nommés CSNA0, CSNB0, etc., de sorte que je ne compterais pas sur cette méthode.

D'autres méthodes / idées / expériences à partager?

Modifier: au fait, voici une implémentation simple en Python consistant à lire les noms de port dans le registre:

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
Était-ce utile?

La solution

Plusieurs options sont disponibles:

  1. Appelez QueryDosDevice à l'aide de la touche NULL lpDeviceName pour répertorier tous les périphériques DOS. Ensuite, utilisez CreateFile et GetCommConfig avec chaque nom d'appareil dans tournez pour savoir s’il s’agit d’un port série.

  2. Appelez SetupDiGetClassDevs avec un ClassGuid de GUID_DEVINTERFACE_COMPORT.

  3. WMI est également disponible en C / C ++ programmes .

Il y a une conversation à propos du groupe de discussion win32 et un CodeProject, projet .

Autres conseils

Utilisation de pySerial avec Python:

import serial.tools.list_ports


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

Le projet PySerial fournit un deux solutions .

Je viens de créer ce qui suit, en lisant EnumSerialPorts dans la source C ++ et en consultant le fonction GetDefaultCommConfig () . Cela ressemblait à la méthode la plus simple utilisant le simple ANSI C et un seul appel API pour chaque port COM possible.

#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;
}

C’est bien assez tard, mais cela m’a été utile!

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

En particulier cet exemple:

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

Il y a un exemple dans la distribution pyserial qui fait cela appelé scanwin32.py

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

Je pense que WMI est la voie à suivre puisqu'il est assez facile de commencer et que le code est minimal. Cela vous évite d’avoir à creuser dans le registre et vous donne une garantie que cela fonctionnera pour des situations plus générales à l’avenir.

Vous pouvez installer tout ce dont vous avez besoin avec pip install pypiwin32 WMI et tout fonctionne à l’origine.

Code

import wmi

query = "SELECT * FROM Win32_PnPEntity WHERE Name LIKE '%(COM%)'"
coms  = wmi.WMI().query(query)

for com in coms:
    print(com.Name)

Sortie

Communications Port (COM1)
mbed Serial Port (COM3)
mbed Serial Port (COM5)

Je suppose que votre port série est une sorte de Plug 'n Play, cela devrait donc fonctionner correctement. Pour une raison quelconque, Win32_SerialPort ne fonctionne pas pour tous les ports.

De nos jours, il existe un one-liner Powershell pour cela.

[System.IO.Ports.SerialPort]::GetPortNames()
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top