2009-07-30 40 views
25

Sto cercando un modo efficace per elencare le porte seriali (COM) disponibili su una macchina Windows. C'è this post about using WMI, ma vorrei qualcosa di meno specifico per .NET. Voglio ottenere l'elenco delle porte in un programma Python o C++, senza .NET.Elenco porte seriali (COM) su Windows?

Io attualmente a conoscenza di altri due approcci:

  1. Leggere le informazioni nella chiave HARDWARE\\DEVICEMAP\\SERIALCOMM Registro di sistema. Questa sembra un'ottima opzione, ma è robusto? Non riesco a trovare una garanzia online o in MSDN che questa cella di registro in effetti detenga sempre l'elenco completo delle porte disponibili.

  2. Tryint per chiamare CreateFile su COMN con N un numero da 1 a qualcosa. Questo non è abbastanza buono, perché alcune porte COM non sono denominate COMN. Ad esempio, alcune porte COM virtuali create sono denominate CSNA0, CSNB0 e così via, quindi non fare affidamento su questo metodo.

Altri metodi/idee/esperienze da condividere?

Edit: a proposito, ecco una semplice implementazione di Python di leggere i nomi delle porte dal Registro di sistema: sono disponibili

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

Grande! Funziona molto bene – luc

+0

Sembra molto utile per trovare le porte COM - Ho intenzione di provare a usarlo per trovare la porta Arduino – SimpleSi

risposta

7

diverse opzioni:

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

  2. Chiama SetupDiGetClassDevs con un ClassGuid di GUID_DEVINTERFACE_COMPORT.

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

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

+0

Cercando di usare QueryDosDevice, ma avendo problemi a sapere quali dispositivi sono le porte seriali. GetCommConfig non fa parte di Pywin32 per qualche motivo –

+2

Sono rimasto impressionato da quanto bene [Teraterm] (http://logmett.com/index.php?/products/teraterm.html) elenca le porte seriali. Ho cercato nel codice sorgente, e risulta, 'ListupSerialPort()' in ['ttcmn.c'] (http://en.sourceforge.jp/projects/ttssh2/svn/view/trunk/teraterm/ttpcmn/ ttcmn.c? view = markup & root = ttssh2) fa riferimento a [quel progetto CodeProject] (http://www.codeproject.com/Articles/2609/Enumerating-serial-ports-W2K-style). –

5

Ho appena creato quanto segue, basato sulla lettura tramite la sorgente C++ a EnumSerialPorts e vedendo la funzione GetDefaultCommConfig(). Sembrava il metodo più semplice che utilizzava semplici ANSI C 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; 
} 
5

Il progetto pySerial fornisce un couple of solutions.

+0

Questa è una funzionalità relativamente nuova per Pyserial ma dovrebbe essere la soluzione corretta in futuro. – theorifice

3

Questo è sicuramente abbastanza tardi, ma si è rivelato utile per me!

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

Grazie per avermi indirizzato al mio post sul blog :-) !! –

+0

Yikes! Piccolo mondo! ... è stato stupido da parte mia. – eatonphil

+0

Nessun problema, è stato divertente vedere :-) –

28

Utilizzando pySerial con Python:

import serial.tools.list_ports 


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

Perfetto, grazie. –

+0

Oppure direttamente dalla riga di comando, 'python -m serial.tools.list_ports' –

2

Credo che WMI è la strada da percorrere in quanto è abbastanza facile per andare avanti e ha codice minimo Ti evita di dover scavare all'interno del registro e ti dà una certa garanzia che funzionerà per situazioni più generali in futuro.

È possibile installare tutto ciò che è necessario con pip install pypiwin32 WMI e funziona immediatamente.

Codice

import wmi 

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

for com in coms: 
    print(com.Name) 

uscita

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

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

2

Al giorno d'oggi c'è un liner Powershell per quello.

[System.IO.Ports.SerialPort]::GetPortNames() 
Problemi correlati