Windowsのシリアル(COM)ポートをリストしますか?
-
05-07-2019 - |
質問
Windowsマシンで使用可能なシリアル(COM)ポートを一覧表示する堅牢な方法を探しています。 WMIの使用に関するこの投稿がありますが、.NET固有ではないものが欲しい-.NETを使用せずに、PythonまたはC ++プログラムのポートのリストを取得したい。
現在、他の2つのアプローチを知っています:
-
HARDWARE \\ DEVICEMAP \\ SERIALCOMM
レジストリキーの情報を読み取る。これは素晴らしいオプションのように見えますが、堅牢ですか?このレジストリセルが常に使用可能なポートの完全なリストを常に保持していることをオンラインまたはMSDNで保証することはできません。 -
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
解決
いくつかのオプションが利用可能です:
-
QueryDosDevice を呼び出しますNULL lpDeviceNameは、すべてのDOSデバイスをリストします。次に、CreateFileと GetCommConfig を使用し、各デバイス名をシリアルポートかどうかを確認します。
-
GUID_DEVINTERFACE_COMPORTのClassGuidで SetupDiGetClassDevs を呼び出します。
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()