web-dev-qa-db-ja.com

Windowsのシリアル(COM)ポートを一覧表示しますか?

Windowsマシンで利用可能なシリアル(COM)ポートを一覧表示するための堅牢な方法を探しています。 WMIの使用に関するこの投稿 がありますが、.NET固有ではないものを希望します-PythonまたはC++プログラムのポートのリストを取得せずに、 。ネット。

私は現在、他の2つのアプローチを知っています。

  1. HARDWARE\\DEVICEMAP\\SERIALCOMMレジストリキーの情報を読み取る。これは素晴らしいオプションのように見えますが、robustですか?オンラインまたはMSDNで、このレジストリセルが実際に常に使用可能なポートの完全なリストを保持しているという保証はありません。

  2. Nに1から何かまでの数を指定して、CreateFileCOMNを呼び出してみてください。一部のCOMポートにはCOMNという名前がないため、これでは不十分です。たとえば、作成された一部の仮想COMポートにはCSNA0、CSNB0などの名前が付いているため、この方法に依存しません。

共有する他の方法/アイデア/経験はありますか?

編集:ちなみに、ここでは簡単なPythonレジストリからポート名を読み取る実装:

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

いくつかのオプションが利用可能です:

  1. すべてのDOSデバイスをリストするには、NULL lpDeviceNameを指定して QueryDosDevice を呼び出します。次に、CreateFileと GetCommConfig を各デバイス名で順番に使用して、シリアルポートかどうかを確認します。

  2. GUID_DEVINTERFACE_COMPORTのClassGuidで SetupDiGetClassDevs を呼び出します。

  3. WMIはC/C++プログラムでも使用可能

win32ニュースグループ と、CodeProjectにいくつかの会話があります project

7
Oren Trutner

PythonでのpySerialの使用:

import serial.tools.list_ports


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

PySerialプロジェクトは ソリューションの組み合わせ を提供します。

6
zdav

C++ソースから EnumSerialPorts を読み取り、関数GetDefaultCommConfig()を確認して、次のコードを作成しました。これは、単純なANSI Cを使用し、可能なCOMポートごとに1つのAPI呼び出しを使用する最も単純な方法のように見えました。

#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

これは間違いなくかなり遅いですが、それは私にとって役に立ちました!

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

特にこの例:

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

今日では、Powershellのワンライナーがあります。

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

Pyserialディストリビューションにscanwin32.pyと呼ばれる例がある

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

2
Ben

WMIは非常に簡単に実行でき、コードも最小限なので、WMIが最適です。レジストリ内を掘り下げる必要がなくなり、将来、より一般的な状況で機能することが保証されます。

pip install pypiwin32 WMIを使用すると、必要なものをすべてインストールでき、すぐに使用できます。

コード

import wmi

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

for com in coms:
    print(com.Name)

出力

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

私の推測では、あなたのシリアルポートはある種のプラグアンドプレイなので、これはうまくいくはずです。何らかの理由でWin32_SerialPortがすべてのポートで機能しない場合があります。

2
Pithikos