web-dev-qa-db-ja.com

Win32で使用可能なシリアルポートのリストを取得するにはどうすればよいですか?

EnumPorts() 関数を呼び出し、「COM」で始まるポート名をフィルタリングすることにより、PCで使用可能なCOMポートのリストを提供するレガシーコードがあります。

テスト目的で、このコードを com0com のようなもので使用できれば、非常に便利です。これは、ヌルモデムとして一緒にループされる仮想COMポートのペアを提供します。

ただし、com0comポートはEnumPorts()関数によって検出されません(「COM」のフィルタリングがなくても)。 HyperTerminalとSysInternals PortMonは両方とも表示できるため、正しくインストールされていると確信しています。

では、利用可能なシリアルポートの決定的なリストを提供する他のWin32関数はありますか?

49
GrahamS

Nick Dが示唆する EnumSerialPorts v1.2 は、nine異なる方法を使用してシリアルポートをリストします!確かに選択肢が不足しているわけではありませんが、結果は異なるようです。

他の人の手間を省くために、ここにそれらをリストし、com0com PCのポート(XP Pro SP2):

  1. CreateFile( "COM" + 1-> 255)Wael Dalloulの提案どおり
    ✔com0comポートが見つかりました。234ミリ秒かかりました。

  2. QueryDosDevice()
    ✔com0comポートが見つかりました。0ミリ秒かかりました。

  3. GetDefaultCommConfig( "COM" + 1-> 255)
    ✔com0comポートが見つかりました。235ミリ秒かかりました。

  4. SETUPAPI.DLLの呼び出しを使用した「SetupAPI1」
    ✔「フレンドリ名」とも報告されているcom0comポートが見つかりましたが、15ミリ秒かかりました。

  5. SETUPAPI.DLLの呼び出しを使用した「SetupAPI2」
    ✘com0comポートが見つかりませんでした。「フレンドリ名」と報告され、32ミリ秒かかりました。

  6. EnumPorts()
    ✘いくつかの非COMポートを報告し、com0comポートが見つからなかったため、15ミリ秒かかりました。

  7. WMI呼び出しの使用
    ✔「フレンドリ名」とも報告されているcom0comポートが見つかり、47ミリ秒かかりました。

  8. MSPORTS.DLLの呼び出しを使用するCOMデータベース
    ✔/✘いくつかの非COMポートを報告し、com0comポートが見つかったため、16ミリ秒かかりました。

  9. レジストリキーHKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMMを反復処理します
    ✔com0comポートが見つかりました。0ミリ秒かかりました。これは明らかに SysInternals PortMon が使用するものです。

これらの結果に基づいて、WMIメソッドは比較的高速で、ボーナスとしてフレンドリ名(たとえば、「Communications Port(COM1)」、「com0com-serial port emulator」)も提供するため、おそらく私の要件に最も適していると思います。

76
GrahamS

簡単なタスクではないようです。

これを確認してください: EnumSerialPorts v1.2

11

たとえば、1〜50のループを作成し、各ポートを開こうとすることができます。ポートが使用可能な場合、オープンが機能します。ポートが使用中の場合、共有エラーが発生します。ポートがインストールされていない場合、ファイルが見つからないというエラーが表示されます。

ポートを開くにはCreateFile APIを使用します。

HANDLE Port = CreateFile(
                  "\\\\.\\COM1",
                  GENERIC_READ | GENERIC_WRITE,
                  0,
                  NULL,
                  OPEN_EXISTING,
                  FILE_ATTRIBUTE_NORMAL,
                  NULL);

その後、結果を確認します。

5
Wael Dalloul

PJ Naughterの EnumSerialPorts をよりポータブルで個別のフォームとして再編成しました。これはより便利です。

互換性を高めるため、C++ではなくCを使用します。

必要な場合、または興味がある場合は、ブロガーの 投稿 にアクセスしてください。

1
Gaiger Chen

私の場合、フルネームとCOMポートアドレスの両方が必要です。物理シリアルポート、USBシリアルポート、およびcom0com仮想シリアルポートがあります。

受け入れられた答えが示唆するように、私はWMI呼び出しを使用しています。 SELECT * FROM Win32_PnPEntityすべてのデバイスを検索します。このような物理デバイスを返し、Captionからアドレスを解析できます。

Serial Port for Barcode Scanner (COM13)

ただし、com0comポートの場合、Captionは次のようになります(アドレスなし):

com0com - serial port emulator

SELECT * FROM Win32_SerialPortは、住所(DeviceID)とフルネーム(Name)を返します。ただし、USBシリアルポートではなく、物理シリアルポートとcom0comポートのみを検出します。

結局、2つのWMI呼び出しが必要です。SELECT * FROM Win32_SerialPort(アドレスはDeviceID)とSELECT * FROM Win32_PnPEntity WHERE Name LIKE '%(COM%'(アドレスはCaptionから解析できます)。 Win32_PnPEntity呼び出しを絞り込んだのは、最初の呼び出しで見つからなかったデバイスのみを検索する必要があるためです。

1
Ville-Valtteri