web-dev-qa-db-fra.com

Liste des ports série (COM) sous Windows?

Je recherche un moyen robuste de répertorier les ports série (COM) disponibles sur une machine Windows. Il y a ce post sur l'utilisation de WMI , mais je voudrais quelque chose de moins spécifique à .NET - je veux obtenir la liste des ports dans un Python ou un programme C++, sans .NET.

Je connais actuellement deux autres approches:

  1. Lire les informations dans le HARDWARE\\DEVICEMAP\\SERIALCOMM clé d'enregistrement. Cela ressemble à une excellente option, mais est-il robuste ? Je ne trouve pas de garantie en ligne ou dans MSDN que cette cellule de registre contient en effet toujours la liste complète des ports disponibles.

  2. Essayez d'appeler CreateFile sur COMN avec N un nombre de 1 à quelque chose. Ce n'est pas suffisant, car certains ports COM ne sont pas nommés COMN. Par exemple, certains ports COM virtuels créés sont nommés CSNA0, CSNB0, etc., donc je ne compterais pas sur cette méthode.

Avez-vous d'autres méthodes/idées/expériences à partager?

Edit: au fait, voici une simple implémentation Python de lecture des noms de port depuis 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
28
Eli Bendersky

Plusieurs options sont disponibles:

  1. Appelez QueryDosDevice avec un lpDeviceName NULL pour répertorier tous les périphériques DOS. Ensuite, utilisez CreateFile et GetCommConfig avec chaque nom de périphérique tour à tour pour déterminer s'il s'agit d'un port série.

  2. Appelez SetupDiGetClassDevs avec un ClassGuid de GUID_DEVINTERFACE_COMPORT.

  3. WMI est également disponible pour les programmes C/C++ .

Il y a une conversation sur le groupe de discussion win32 et un CodeProject, euh, projet .

7
Oren Trutner

Utilisation de pySerial avec Python:

import serial.tools.list_ports


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

Le projet PySerial fournit un couple de solutions .

6
zdav

Je viens de créer ce qui suit, basé sur la lecture de la source C++ dans EnumSerialPorts et sur la fonction GetDefaultCommConfig(). Cela ressemblait à la méthode la plus simple utilisant un simple C ANSI et un seul appel d'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;
}
5
tomlogic

C'est certainement 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
3
eatonphil

De nos jours, il existe une doublure Powershell pour cela.

[System.IO.Ports.SerialPort]::GetPortNames()
2
Paul Williams

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

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

2
Ben

Je pense que WMI est le chemin à parcourir car il est assez facile de démarrer et il a un code minimal. Il vous évite d'avoir à creuser dans le registre et vous donne une garantie qu'il fonctionnera pour des situations plus générales à l'avenir.

Vous pouvez installer tout le nécessaire avec pip install pypiwin32 WMI et cela fonctionne tout de suite.

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 & Play, cela devrait donc fonctionner correctement. Pour certaines raisons Win32_SerialPort ne fonctionne pas pour tous les ports.

2
Pithikos