2013-04-19 19 views
5

私はcportを使って複数のシリアルポートにアクセスするプログラムを持っています。シリアル(COM)ポートの名前またはID

これまでコンフィギュレーションするには、コンボボックスに利用可能なすべてのコンポートを列挙して選択するだけでしたが、(仮想)シリアルインターフェイスを持つドライバの数が増えれば、エンドユーザの設定が面倒になりました。

現在の検出機能はcreatefile()で動作しますが、情報が存在する/存在しないとか、 "ビジー"しかないという問題があります。

しかし改善するためには、COMポートごとに、接続されているハードウェアデバイス/ドライバ(デバイスマネージャ)のような識別文字列が必要です。これにより、ユーザーがコンパイルを絞り込むことが容易になります(有限のシリアルカードを配信するので)

おそらくWMIから入手できますが、それはかなりジャングルです.SBにはより具体的な情報があります、コード?

(デルファイXE3、win7の+、追加のインストールや展開をしてください必要がありませんソリューション)

+0

[マシンにシリアルポートが物理的に存在するかどうかを判断する方法](http://stackoverflow.com/questions/5575372/how-to-determine-if-a-machine-physically-has-a) -serial-port) –

+0

また:http://stackoverflow.com/q/613166/327083 ...この機能を高レベルで提供するjediなどのコンポーネントがありますが、自分でロールしたい場合は、 WMIまたはレジストリのいずれかがあなたの唯一の手段です。 –

+0

探しているのはおそらく、 "フレンドリネーム"を含むcomポートを列挙する方法でしょうか? –

答えて

9

あなたがSetupAPIGUID_DEVINTERFACE_COMPORTデバイスインターフェイスクラスを使用することができフレンドリ名を取得するCOMポートを列挙したい場合。 JvSetupApiユニットJVCLライブラリの一部である:

はこれがそう

enter image description here

ノートのようなものが返されます

{$APPTYPE CONSOLE} 

{$R *.res} 

uses 
    Windows, 
    SysUtils, 
    JvSetupApi; 

const 
    GUID_DEVINTERFACE_COMPORT:TGUID='{86E0D1E0-8089-11D0-9CE4-08003E301F73}'; 

procedure EnumerateCOMPorts; 
var 
    cbRequired : DWORD; 
    hdev  : HDEVINFO; 
    idev  : Integer; 
    did  : TSPDeviceInterfaceData; 
    pdidd : PSPDeviceInterfaceDetailData; 
    PropertyBuffer : array[0..255] of Char; 
    DeviceInfoData: TSPDevInfoData; 
    PropertyRegDataType: DWORD; 
    RequiredSize: DWORD; 
begin 
    // enumerate the com ports 
    hdev := SetupDiGetClassDevs(@GUID_DEVINTERFACE_COMPORT, nil, 0, DIGCF_PRESENT OR DIGCF_DEVICEINTERFACE); 
    if (INVALID_HANDLE_VALUE <> THandle(hdev)) then 
    begin 
    try 
     idev:=0; 
     ZeroMemory(@did, SizeOf(did)); 
     did.cbSize := SizeOf(did); 
     repeat 
     if (SetupDiEnumDeviceInterfaces(hdev, nil, GUID_DEVINTERFACE_COMPORT, idev, did)) then 
     begin 
      cbRequired := 0; 
      SetupDiGetDeviceInterfaceDetail(hdev, @did, nil, 0, cbRequired, nil); 
      if (ERROR_INSUFFICIENT_BUFFER= GetLastError()) then 
      begin 
       pdidd:=AllocMem(cbRequired); 
       try 
       pdidd.cbSize := SizeOf(TSPDeviceInterfaceDetailData); 
       DeviceInfoData.cbSize:= SizeOf(DeviceInfoData); 
       RequiredSize:=0; 
       if (SetupDiGetDeviceInterfaceDetail(hdev, @did, pdidd, cbRequired, RequiredSize, @DeviceInfoData)) then 
       begin 

       PropertyRegDataType:=0; 
       RequiredSize:=0; 
       if SetupDiGetDeviceRegistryProperty(hdev, DeviceInfoData, SPDRP_FRIENDLYNAME, PropertyRegDataType, PBYTE(@PropertyBuffer[0]), SizeOf(PropertyBuffer), RequiredSize) then 
        Writeln(Format('Friendly Name - %s',[PropertyBuffer])); 

       if SetupDiGetDeviceRegistryProperty(hdev, DeviceInfoData, SPDRP_DEVICEDESC, PropertyRegDataType, PBYTE(@PropertyBuffer[0]), SizeOf(PropertyBuffer), RequiredSize) then 
        Writeln(Format('Description - %s',[PropertyBuffer])); 

       if SetupDiGetDeviceRegistryProperty(hdev, DeviceInfoData, SPDRP_LOCATION_INFORMATION, PropertyRegDataType, PBYTE(@PropertyBuffer[0]), SizeOf(PropertyBuffer), RequiredSize) then 
        Writeln(Format('Location  - %s',[PropertyBuffer])); 
       end 
       else 
       RaiseLastOSError; 
       finally 
       FreeMem(pdidd); 
       end; 
      end; 
     end 
     else 
     Break; 
     inc(idev); 
     until false; 
    finally 
     SetupDiDestroyDeviceInfoList(hdev); 
    end; 
    end; 
end; 

begin 
    try 
    if not LoadsetupAPI then exit; 
    EnumerateCOMPorts; 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
    readln; 
end. 

このサンプルを試してみてください。

+0

ええ、その間にも他の参考文献からの作業があります。すべてのポートを表示するわけではありません。私はさまざまなWMIの例を試してきましたが、これと同じように表示するか、または高度を必要とします(さらに、すべてのCOM デバイスを見ることができません) –

+1

あなたのコードは間違いがあるようです1つのデバイスのみを表示します。 'SetupDiEnumDeviceInterfaces(hdev、nil、GUID_DEVINTERFACE_COMPORT、idev、did) 'への次の呼び出しは、' SetupDiDestroyDeviceInfoList(hdev) 'が' hdev'を破棄するため、 'try..finally'セクションがrepeatループの外側に必要です。リターンエラー(6 - 無効なハンドル)。 – AntonBazhal

+0

@AntonBazhal、ありがとう。私はコードを編集してtry finallyブロックを動かしました。 – RRUZ

0

COMxx形式の短い名前には、HKEY_LOCAL_MACHINE \ HARDWARE \ DEVICEMAP \ SERIALCOMMを使用できます。管理者権限/ UACの必要性を避けるために、読み取り専用アクセスを指定してください。 usb232アダプターと実際の通信ポートの両方を見ることができます。

また、HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Enum \ Root \ PORTSをチェクすることもできますが、ちょっと難しいようです。

関連する問題