I've a program that access multiple serial ports using cport.
To configure, till now I simply listed all available comports in a combobox to make a selection, but the increasing number of drivers with (virtual) serial interfaces makes configuring for end-users troublesome.
The current detection works with createfile(), but that has the problem that you only get exists/nonexists and maybe "busy" as information.
However to improve, I need per COM port a identification string, like the hardware device/driver (device manager) it is connected too. This would make it easier for the user to narrow the comports down (since we deliver a finite number of serial cards)
Probably it is available from WMI, but that's quite a jungle, does sb have more concrete information, or better, code?
(Delphi XE3, Win7+, no solution that requires additional installing or deployment please)
Open Device Manager (Start → Control Panel → Hardware and Sound → Device Manager) Look in the Device Manager list, open the category "Ports", and find the matching COM Port. Take the number in the bracket behind the port description.
An asynchronous port on the computer used to connect a serial device to the computer and capable of transmitting one bit at a time. Serial ports are usually identified on IBM compatible computers as COM (communications) ports. For example, a mouse might connect to COM1 and a modem to COM2.
There are two types of serial ports that are commonly found on a computer: DB-25 and DE-9.
If you want enumerate the COM ports getting a friendly name you can use the SetupAPI
and the GUID_DEVINTERFACE_COMPORT
device interface class.
Try this sample
{$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.
This will return something like so
Note : The JvSetupApi
unit is part of the JVCL library.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With