Windowsマシンで利用可能なシリアル(COM)ポートを一覧表示するための堅牢な方法を探しています。 WMIの使用に関するこの投稿 がありますが、.NET固有ではないものを希望します-PythonまたはC++プログラムのポートのリストを取得せずに、 。ネット。
私は現在、他の2つのアプローチを知っています。
HARDWARE\\DEVICEMAP\\SERIALCOMM
レジストリキーの情報を読み取る。これは素晴らしいオプションのように見えますが、robustですか?オンラインまたはMSDNで、このレジストリセルが実際に常に使用可能なポートの完全なリストを保持しているという保証はありません。
Nに1から何かまでの数を指定して、CreateFile
でCOMN
を呼び出してみてください。一部の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
いくつかのオプションが利用可能です:
すべてのDOSデバイスをリストするには、NULL lpDeviceNameを指定して QueryDosDevice を呼び出します。次に、CreateFileと GetCommConfig を各デバイス名で順番に使用して、シリアルポートかどうかを確認します。
GUID_DEVINTERFACE_COMPORTのClassGuidで SetupDiGetClassDevs を呼び出します。
win32ニュースグループ と、CodeProjectにいくつかの会話があります project 。
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
今日では、Powershellのワンライナーがあります。
[System.IO.Ports.SerialPort]::GetPortNames()
Pyserialディストリビューションに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
がすべてのポートで機能しない場合があります。