bestlong 怕失憶論壇's Archiver

bestlong 發表於 2011-3-14 16:17

列出 windows 所有的 RS232 COM Port 列表

機碼 HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM 就紀錄所有的 COM Port.



所以可以使用讀取機碼的方式來取得 COM Port 列表[code]unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Registry, StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
  reg : TRegistry;
  sl: TStrings;
  i: integer;
begin
  Memo1.Clear;
  reg := TRegistry.Create;
  try
    reg.RootKey := HKEY_LOCAL_MACHINE;
    reg.OpenKey('HARDWARE\DEVICEMAP\SERIALCOMM', false);
    sl := TStringList.Create;
    try
      reg.GetValueNames(sl);
      for i := 0 to sl.Count -1 do
        Memo1.Lines.Add(reg.ReadString(sl.Strings[i]));
    finally
      sl.Free;
    end;
  finally
    reg.CloseKey;
    reg.free;
  end;
end;

end.
[/code]

bestlong 發表於 2013-8-9 11:06

配合作業系統的安全性架構,在 Open Key 之前最好要設定存取等級

reg.RootKey := HKEY_LOCAL_MACHINE;
[color=Red]reg.Access := KEY_READ;[/color]
reg.OpenKey('HARDWARE\DEVICEMAP\SERIALCOMM', false);

bestlong 發表於 2013-8-9 11:09

只有 COMn 的列表也不是很確定是對應到哪個設備,需要更友善的資訊

[url]http://delphi.cjcsoft.net/viewthread.php?tid=45021[/url]

[b]Enumerating available comm ports with friendly names.[/b]
Title: Enumerating available comm ports with friendly names.

Question: Serial (and virtual serial) PNP Devices (PCMCIA, USB, Bluetooth) get assigned "arbitrary" comm port numbers.
To help users to select the correct comm port it would be helpfull to list them with device friendly names.
The supplied function helps this goal.


Answer:[code](*

The function below returns a list of available COM-ports
(not open by this or an other process), with friendly names. The list is formatted as follows:

COM1: = Communications Port (COM1)
COM5: = NI Serial Port (Com5)
COM6: = NI Serial Port (Com6)
COM7: = USB Serial Port (COM7)
COM8: = Bluetooth Communications Port (COM8)
COM9: = Bluetooth Communications Port (COM9)



The function uses the setupapi (setup api) unit that is available from
"http://homepages.borland.com/jedi/cms/modules/apilib/visit.php?cid=4&lid=3".

I have verified the code and it worked  for W2000, WXP, W98. It does not work for W95, and NT 4.0. I did not check WME but I guess it will work with WME too.


*)

function SetupEnumAvailableComPorts:TstringList;
// Enumerates all serial communications ports that are available and ready to
// be used.

// For the setupapi unit see
// http://homepages.borland.com/jedi/cms/modules/apilib/visit.php?cid=4&lid=3

var
  RequiredSize:             Cardinal;
  Guid:                     TGUID;
  DevInfoHandle:            HDEVINFO;
  DeviceInfoData:           TSPDevInfoData;
  MemberIndex:              Cardinal;
  PropertyRegDataType:      DWord;
  RegProperty:              Cardinal;
  RegTyp:                   Cardinal;
  Key:                      Hkey;
  Info:                     TRegKeyInfo;
  S1,S2:                    string;
  hc:                       THandle;
begin
  Result:=Nil;
//If we cannot access the setupapi.dll then we return a nil pointer.   
  if not LoadsetupAPI then exit;
  try
// get 'Ports' class guid from name
    if SetupDiClassGuidsFromName('Ports',@Guid,RequiredSize,RequiredSize) then begin
//get object handle of 'Ports' class to interate all devices
       DevInfoHandle:=SetupDiGetClassDevs(@Guid,Nil,0,DIGCF_PRESENT);
       if Cardinal(DevInfoHandle)Invalid_Handle_Value then begin
         try
           MemberIndex:=0;
           result:=TStringList.Create;
//iterate device list
           repeat
             FillChar(DeviceInfoData,SizeOf(DeviceInfoData),0);
             DeviceInfoData.cbSize:=SizeOf(DeviceInfoData);
//get device info that corresponds to the next memberindex
             if Not SetupDiEnumDeviceInfo(DevInfoHandle,MemberIndex,DeviceInfoData) then
               break;
//query friendly device name LIKE 'BlueTooth Communication Port (COM8)' etc
             RegProperty:=SPDRP_FriendlyName;{SPDRP_Driver, SPDRP_SERVICE, SPDRP_ENUMERATOR_NAME,SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,SPDRP_FRIENDLYNAME,}
             SetupDiGetDeviceRegistryProperty(DevInfoHandle,DeviceInfoData,
                                                   RegProperty,
                                                   @PropertyRegDataType,
                                                   NIL,0,@RequiredSize);
             SetLength(S1,RequiredSize);
             if SetupDiGetDeviceRegistryProperty(DevInfoHandle,DeviceInfoData,
                                                 RegProperty,
                                                 @PropertyRegDataType,
                                                 @S1[1],RequiredSize,@RequiredSize) then begin
               KEY:=SetupDiOpenDevRegKey(DevInfoHandle,DeviceInfoData,DICS_FLAG_GLOBAL,0,DIREG_DEV,KEY_READ);
               if keyINValid_Handle_Value then begin
                 FillChar(Info, SizeOf(Info), 0);
//query the real port name from the registry value 'PortName'
                 if RegQueryInfoKey(Key, nil, nil, nil, @Info.NumSubKeys,@Info.MaxSubKeyLen, nil, @Info.NumValues, @Info.MaxValueLen,
                                                        @Info.MaxDataLen, nil, @Info.FileTime) = ERROR_SUCCESS then begin
                   RequiredSize:= Info.MaxValueLen + 1;
                   SetLength(S2,RequiredSize);
                   if RegQueryValueEx(KEY,'PortName',Nil,@Regtyp,@s2[1],@RequiredSize)=Error_Success then begin
                     If (Pos('COM',S2)=1) then begin
//Test if the device can be used
                       hc:=CreateFile(pchar('\\.\'+S2+#0),
                                      GENERIC_READ or GENERIC_WRITE,
                                      0,
                                      nil,
                                      OPEN_EXISTING,
                                      FILE_ATTRIBUTE_NORMAL,
                                      0);
                       if hc INVALID_HANDLE_VALUE then begin
                         Result.Add(Strpas(PChar(S2))+': = '+StrPas(PChar(S1)));
                         CloseHandle(hc);
                       end;
                     end;
                   end;
                 end;
                 RegCloseKey(key);
               end;
             end;
             Inc(MemberIndex);
           until False;
//If we did not found any free com. port we return a NIL pointer.
           if Result.Count=0 then begin
             Result.Free;
             Result:=NIL;

           end
         finally
           SetupDiDestroyDeviceInfoList(DevInfoHandle);
         end;
       end;
    end;
  finally
    UnloadSetupApi;
  end;
end;[/code]
頁: [1]

Powered by Discuz! X1.5 Archiver   © 2001-2010 Comsenz Inc.