2009-07-30 42 views
25

Tôi đang tìm một cách mạnh mẽ để liệt kê các cổng nối tiếp (COM) có sẵn trên máy Windows. Có this post about using WMI, nhưng tôi muốn một cái gì đó ít .NET cụ thể - Tôi muốn có được danh sách các cổng trong một chương trình Python hoặc C++, mà không có .NET.Liệt kê các cổng nối tiếp (COM) trên Windows?

Tôi hiện biết của hai cách tiếp cận khác:

  1. Đọc các thông tin trong khóa HARDWARE\\DEVICEMAP\\SERIALCOMM registry. Điều này trông giống như một lựa chọn tuyệt vời, nhưng có phải là mạnh mẽ? Tôi không thể tìm thấy một bảo đảm trực tuyến hoặc trong MSDN rằng tế bào đăng ký này thực sự luôn luôn giữ danh sách đầy đủ các cổng có sẵn.

  2. Cố gắng gọi CreateFile trên COMN bằng N số từ 1 đến thứ gì đó. Điều này là không đủ tốt, bởi vì một số cổng COM không được đặt tên COMN. Ví dụ, một số cổng COM ảo được tạo có tên là CSNA0, CSNB0, v.v., vì vậy tôi sẽ không dựa vào phương pháp này.

Bất kỳ phương pháp/ý tưởng/kinh nghiệm nào khác để chia sẻ?

Edit: bằng cách này, đây là một việc thực hiện Python đơn giản của việc đọc tên cổng từ registry:

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

Tuyệt vời! Nó hoạt động rất tốt – luc

+0

Có vẻ rất hữu ích để tìm cổng com - Tôi sẽ cố gắng và sử dụng nó để tìm cổng Arduino – SimpleSi

Trả lời

7

Một số tùy chọn có sẵn:

  1. Gọi QueryDosDevice với một NULL lpDeviceName liệt kê tất cả các thiết bị DOS. Sau đó, sử dụng CreateFile và GetCommConfig với mỗi tên thiết bị lần lượt để tìm ra cho dù đó là một cổng nối tiếp.

  2. Gọi SetupDiGetClassDevs với ClassGuid của GUID_DEVINTERFACE_COMPORT.

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

Có một số cuộc trò chuyện trên win32 newsgroup và CodeProject, er, project.

+0

Đang cố sử dụng QueryDosDevice, nhưng gặp sự cố khi biết thiết bị nào là cổng nối tiếp. GetCommConfig không phải là một phần của Pywin32 vì lý do nào đó –

+2

Tôi đã rất ấn tượng về việc [Teraterm] (http://logmett.com/index.php?/products/teraterm.html) liệt kê các cổng nối tiếp như thế nào. Tôi nhìn vào mã nguồn, và nó quay ra, 'ListupSerialPort()' trong ['ttcmn.c'] (http://en.sourceforge.jp/projects/ttssh2/svn/view/trunk/teraterm/ttpcmn/ ttcmn.c? view = markup & root = ttssh2) đề cập đến [dự án CodeProject] (http://www.codeproject.com/Articles/2609/Enumerating-serial-ports-W2K-style). –

5

Tôi vừa tạo thông tin sau, dựa trên việc đọc qua nguồn C++ tới EnumSerialPorts và xem hàm GetDefaultCommConfig(). Nó trông giống như phương pháp đơn giản nhất bằng cách sử dụng đơn giản ANSI C và một cuộc gọi API duy nhất cho mỗi cổng COM có thể.

#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

Dự án PySerial cung cấp couple of solutions.

+0

Đây là một tính năng tương đối mới cho Pyserial nhưng phải là giải pháp chính xác trong tương lai. – theorifice

3

này chắc chắn là khá muộn, nhưng nó tỏ ra hữu ích cho tôi!

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

Riêng ví dụ này:

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

Cảm ơn bạn đã chỉ cho tôi bài đăng trên blog của riêng mình :-) !! –

+0

Yikes! Thế giới nhỏ bé ... thật ngu ngốc với tôi. – eatonphil

+0

Đừng lo lắng, thật thú vị khi thấy :-) –

28

Sử dụng pySerial với Python:

import serial.tools.list_ports 


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

Hoàn hảo, cảm ơn. –

+0

Hoặc trực tiếp từ dòng lệnh, 'python -m serial.tools.list_ports' –

2

Tôi nghĩ rằng WMI là con đường để đi vì nó khá dễ dàng để có được đi và nó có mã tối thiểu. Nó giúp bạn tiết kiệm từ việc phải đào sâu bên trong registry và cung cấp cho bạn một số bảo đảm rằng nó sẽ làm việc cho các tình huống tổng quát hơn trong tương lai.

Bạn có thể cài đặt mọi thứ cần thiết với pip install pypiwin32 WMI và nó hoạt động ngoài hộp.

import wmi 

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

for com in coms: 
    print(com.Name) 

Output

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

tôi đoán là cổng nối tiếp của bạn là một số loại Plug 'n Play để này nên hoạt động tốt. Vì một số lý do, Win32_SerialPort không hoạt động với tất cả các cổng.

2

Ngày nay, có một lớp lót Powershell cho điều đó.

[System.IO.Ports.SerialPort]::GetPortNames() 
Các vấn đề liên quan