Pergunta

Eu estou procurando uma maneira robusta para listar o serial disponível (COM) portas em uma máquina Windows. Há este post sobre como usar WMI , mas eu gostaria de algo menos .NET específica - quero obter a lista de portas em um programa C ++ Python ou, sem .NET

.

Actualmente, eu sei de duas outras abordagens:

  1. Ler as informações na chave de registo HARDWARE\\DEVICEMAP\\SERIALCOMM. Este parece ser uma ótima opção, mas é robusta ? Não consigo encontrar uma garantia on-line ou no MSDN que esta célula Registro de fato sempre mantém a lista completa de portas disponíveis.

  2. Tryint chamar CreateFile em COMN com N um número de 1 a algo. Isso não é bom o suficiente, porque algumas portas COM não são nomeados COMN. Por exemplo, algumas portas COM virtuais criadas são nomeadas CSNA0, CSNB0, e assim por diante, então eu não iria contar com este método.

Qualquer métodos other / ideias / experiência para partilhar?

Editar: , a propósito, aqui está uma implementação simples Python de ler os nomes das portas a partir do 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
Foi útil?

Solução

Várias opções estão disponíveis:

  1. QueryDosDevice com um NULL lpDeviceName para listar todos os dispositivos DOS. Em seguida, use CreateFile e GetCommConfig com cada nome de dispositivo em virar para descobrir se é uma porta serial.

  2. SetupDiGetClassDevs com um ClassGuid de GUID_DEVINTERFACE_COMPORT.

  3. WMI também está disponível para C / C ++ programas .

Há alguma conversa no win32 newsgroup e uma CodeProject, er, projeto .

Outras dicas

Usando pyserial com Python:

import serial.tools.list_ports


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

O projeto PySerial fornece uma de soluções .

Acabei de criar o seguinte, com base na leitura através do C ++ fonte para EnumSerialPorts e vendo o função GetDefaultCommConfig(). Parecia que o método mais simples usando simples ANSI C e uma chamada API única para cada porta COM possível.

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

Este é definitivamente bastante tarde, mas revelou-se útil para mim!

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

Particularmente este exemplo:

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

Há um exemplo na distro pyserial agora que faz isso chamado scanwin32.py

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

Eu acho WMI é o caminho a percorrer, uma vez que é muito fácil para começar e tem o mínimo de código. Conserva-o de ter que cavar dentro do registro e lhe dá alguma garantia de que ele vai trabalhar para situações mais gerais no futuro.

Você pode instalar tudo o necessário com pip install pypiwin32 WMI e funciona out-of-the-box.

Código

import wmi

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

for com in coms:
    print(com.Name)

saída

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

Meu palpite é que a porta serial é algum tipo de Plug 'n Play por isso deve funcionar bem. Por alguma razão Win32_SerialPort não funciona para todas as portas.

Hoje em dia há um one-liner PowerShell para isso.

[System.IO.Ports.SerialPort]::GetPortNames()
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top