我有一个使用cport访问多个串口的程序。
要进行配置,到目前为止我只是在组合框中列出所有可用的组件进行选择,但越来越多的带有(虚拟)串行接口的驱动程序使得为最终用户配置很麻烦。
当前检测与createfile()一起使用,但是这个问题是你只能获得exists / nonexists并且可能“忙”作为信息。
但是为了改进,我需要每个COM端口一个标识字符串,就像它连接的硬件设备/驱动程序(设备管理器)一样。这将使用户更容易缩小范围(因为我们提供有限数量的串行卡)
可能它可以从WMI获得,但这是一个相当丛林,是否有更具体的信息或更好的代码?
(Delphi XE3,Win7 +,没有需要额外安装或部署的解决方案)
答案 0 :(得分:9)
如果要枚举COM端口获取友好名称,可以使用SetupAPI
和GUID_DEVINTERFACE_COMPORT
设备接口类。
试试这个样本
{$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.
这将返回类似的内容
注意:JvSetupApi
单位是JVCL库的一部分。
答案 1 :(得分:0)
您可以将HKEY_LOCAL_MACHINE \ HARDWARE \ DEVICEMAP \ SERIALCOMM用于COMxx样式的短名称。请记住指定只读访问权限以避免管理员权限/ UAC必要性。您可以看到usb232适配器和真正的通信端口。
你也可以去HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Enum \ Root \ PORTS,但这看起来有点棘手。