質問

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

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

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

  2. COMN CreateFile を、Nに1から何かの数字を付けて呼び出すようにしてください。一部の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
役に立ちましたか?

解決

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

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

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

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

win32ニュースグループおよびCodeProject、er、プロジェクト

他のヒント

PythonでのpySerialの使用:

import serial.tools.list_ports


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

PySerialプロジェクトは、ソリューションのカップルを提供します。

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

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

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

pywin distroにはscanwin32.pyと呼ばれるこれを行う例があります

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

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 はすべてのポートで機能しません。

最近は、Powershellのワンライナーがあります。

[System.IO.Ports.SerialPort]::GetPortNames()
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top