2009-07-30 70 views
25

Estoy buscando una manera robusta para listar los puertos serie (COM) disponibles en una máquina Windows. Hay this post about using WMI, pero me gustaría algo menos específico .NET - Quiero obtener la lista de puertos en un programa C++ o Python, sin .NET.Listado de puertos serie (COM) en Windows?

Actualmente me conocerán otros dos enfoques:

  1. La lectura de la información en la clave HARDWARE\\DEVICEMAP\\SERIALCOMM registro. Esto parece ser una gran opción, pero ¿es robusta? No puedo encontrar una garantía en línea o en MSDN de que esta celda de registro siempre contenga la lista completa de puertos disponibles.

  2. Tryint para llamar a CreateFile en COMN con N un número de 1 a algo. Esto no es lo suficientemente bueno, porque algunos puertos COM no se llaman COMN. Por ejemplo, algunos puertos COM virtuales creados se llaman CSNA0, CSNB0, etc., así que no confiaría en este método.

¿Algún otro método/ideas/experiencia para compartir?

Editar: por cierto, he aquí una sencilla implementación de Python de la lectura de los nombres de los puertos de 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 
+0

Genial! Funciona muy bien – luc

+0

Parece muy útil para encontrar puertos de comunicación: voy a tratar de usarlo para encontrar el puerto Arduino – SimpleSi

Respuesta

7

Varias opciones están disponibles:

  1. llamada QueryDosDevice con un nulo lpDeviceName para listar todos los dispositivos DOS. A continuación, utilice CreateFile y GetCommConfig con cada nombre de dispositivo a su vez de averiguar si se trata de un puerto serie.

  2. Llama a SetupDiGetClassDevs con una ClassGuid de GUID_DEVINTERFACE_COMPORT.

  3. WMI is also available to C/C++ programs.

Hay un poco de conversación en el win32 newsgroup y una CodeProject, er, project.

+0

Intentando utilizar QueryDosDevice, pero tengo problemas para saber qué dispositivos son puertos serie. GetCommConfig no es parte de Pywin32 por alguna razón –

+2

Me ha impresionado lo bien que [Teraterm] (http://logmett.com/index.php?/products/teraterm.html) enumera los puertos serie. Busqué en el código fuente, y resulta que, 'ListupSerialPort()' en ['ttcmn.c'] (http://en.sourceforge.jp/projects/ttssh2/svn/view/trunk/teraterm/ttpcmn/ ttcmn.c? view = markup & root = ttssh2) se refiere a [ese proyecto de CodeProject] (http://www.codeproject.com/Articles/2609/Enumerating-serial-ports-W2K-style). –

5

Acabo de crear lo siguiente, basado en la lectura a través de la fuente C++ a EnumSerialPorts y viendo la función GetDefaultCommConfig(). Parecía el método más simple usando ANSI C simple y una única llamada API para cada posible puerto 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; 
} 
5

El proyecto PySerial proporciona un couple of solutions.

+0

Esta es una característica relativamente nueva para Pyserial pero debería ser la solución correcta en el futuro. – theorifice

3

Esto es definitivamente bastante tarde, pero resultó útil para mí!

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

Particularmente este ejemplo:

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 
+14

Gracias por indicarme mi propia entrada de blog :-) !! –

+0

¡Yikes! ¡Pequeño mundo! ... eso fue estúpido de mi parte. – eatonphil

+0

No se preocupe, fue divertido de ver :-) –

28

Usando PySerial con Python:

import serial.tools.list_ports 


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

Perfecto, gracias. –

+0

O directamente desde la línea de comando, 'python -m serial.tools.list_ports' –

2

Creo WMI es el camino a seguir, ya que es bastante fácil para ponerse en marcha y tiene código mínimo Le ahorra tener que cavar dentro del registro y le da cierta garantía de que funcionará para situaciones más generales en el futuro.

Puede instalar todo lo necesario con pip install pypiwin32 WMI y funciona de fábrica.

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) 

salida

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

Mi conjetura es que el puerto serie es una especie de Plug 'n Play por lo que este debería funcionar bien. Por algún motivo, Win32_SerialPort no funciona para todos los puertos.

2

Hoy en día existe un diseño único de Powershell para eso.

[System.IO.Ports.SerialPort]::GetPortNames() 
Cuestiones relacionadas