It's just a first try, but the output works here with Windows 7 and PB v6.11 x64.
Code: Select all
; https://nakov.com/blog/2009/05/10/enumerate-all-com-ports-and-find-their-name-and-description-in-c/
EnableExplicit
#DICS_FLAG_GLOBAL = 1
#DIREG_DEV = 1
#SPDRP_DEVICEDESC = 0
Structure uDeviceInfo
sName.s
sDescription.s
EndStructure
Structure uSpDevInfoData Align #PB_Structure_AlignC
cbSize.l
ClassGuid.GUID
DevInst.l
*Reserved
EndStructure
Prototype.i ptSetupDiGetClassDevs(*ClassGuid, *pctstrEnumerator, hwndParent.i, dwFlags.l)
Prototype.i ptSetupDiEnumDeviceInfo(hDevInfoSet.i, dwMemberIndex.l, *DevInfoData)
Prototype.i ptSetupDiOpenDevRegKey(hDevInfoSet.i, *DeviceInfoData, dwScope.l, dwHwProfile.l, dwKeyType.l, dwSamDesired.l)
Prototype.i ptSetupDiGetDeviceRegistryProperty(hDevInfoSet.i, *DeviceInfoData, dwProperty.l, *dwPropertyRegDataType,
*bytePropertyBuffer, dwPropertyBufferSize.l, *dwRequiredSize)
Prototype.i ptSetupDiDestroyDeviceInfoList(hDevInfoSet.i)
Global SetupDiGetClassDevs.ptSetupDiGetClassDevs
Global SetupDiEnumDeviceInfo.ptSetupDiEnumDeviceInfo
Global SetupDiOpenDevRegKey.ptSetupDiOpenDevRegKey
Global SetupDiGetDeviceRegistryProperty.ptSetupDiGetDeviceRegistryProperty
Global SetupDiDestroyDeviceInfoList.ptSetupDiDestroyDeviceInfoList
Procedure.i LibraryInit()
Protected iReturn.i, fResult.i, iSetupApiLibNumber.i
iSetupApiLibNumber = OpenLibrary(#PB_Any, "setupapi.dll")
iReturn = iSetupApiLibNumber
fResult = Bool(iSetupApiLibNumber)
If Not fResult
Debug "Error LibraryInit()->OpenLibrary() setupapi.dll"
EndIf
If fResult
SetupDiGetClassDevs = GetFunction(iSetupApiLibNumber, "SetupDiGetClassDevsW")
SetupDiEnumDeviceInfo = GetFunction(iSetupApiLibNumber, "SetupDiEnumDeviceInfo")
SetupDiOpenDevRegKey = GetFunction(iSetupApiLibNumber, "SetupDiOpenDevRegKey")
SetupDiGetDeviceRegistryProperty = GetFunction(iSetupApiLibNumber, "SetupDiGetDeviceRegistryPropertyW")
SetupDiDestroyDeviceInfoList = GetFunction(iSetupApiLibNumber, "SetupDiDestroyDeviceInfoList")
If Not SetupDiGetClassDevs
fResult = #False
Debug "Error LibraryInit()->GetFunction() SetupDiGetClassDevs"
EndIf
If Not SetupDiEnumDeviceInfo
fResult = #False
Debug "Error LibraryInit()->GetFunction() SetupDiEnumDeviceInfo"
EndIf
If Not SetupDiOpenDevRegKey
fResult = #False
Debug "Error LibraryInit()->GetFunction() SetupDiOpenDevRegKey"
EndIf
If Not SetupDiGetDeviceRegistryProperty
fResult = #False
Debug "Error LibraryInit()->GetFunction() SetupDiGetDeviceRegistryProperty"
EndIf
If Not SetupDiDestroyDeviceInfoList
fResult = #False
Debug "Error LibraryInit()->GetFunction() SetupDiDestroyDeviceInfoList"
EndIf
EndIf
If Not fResult
If iSetupApiLibNumber
CloseLibrary(iSetupApiLibNumber)
EndIf
iReturn = #Null
EndIf
ProcedureReturn iReturn
EndProcedure
Procedure LibraryExit(iLibNumber.i)
If iLibNumber
CloseLibrary(iLibNumber)
EndIf
EndProcedure
Procedure.s GetSerialName(hDeviceInfoSet.i, *uSpDevInfoData.uSpDevInfoData)
Protected sReturn.s, iResult.i, hDeviceRegistryKey.i
Protected iRegKeyType.l, sDeviceNameBuffer.s, iLength.l
hDeviceRegistryKey = SetupDiOpenDevRegKey(hDeviceInfoSet, *uSpDevInfoData,
#DICS_FLAG_GLOBAL, 0, #DIREG_DEV, #KEY_QUERY_VALUE)
If Not hDeviceRegistryKey
Debug "Error GetSerialName()->SetupDiOpenDevRegKey() Failed To open a registry key For device-specific configuration information"
Else
iLength = 256
sDeviceNameBuffer = Space(iLength)
iResult = RegQueryValueEx_(hDeviceRegistryKey, @"PortName", #Null, @iRegKeyType, @sDeviceNameBuffer, @iLength)
If (iResult <> #ERROR_SUCCESS)
Debug "Error " + iResult + " GetSerialName()->RegQueryValueEx_() Can Not Read registry value PortName For device"
Else
RegCloseKey_(hDeviceRegistryKey)
sReturn = sDeviceNameBuffer
EndIf
EndIf
ProcedureReturn sReturn
EndProcedure
Procedure.s GetSerialDescription(hDeviceInfoSet.i, *uSpDevInfoData.uSpDevInfoData)
Protected sReturn.s, iResult.i
Protected sDescriptionBuffer.s, iLength.l, iPropRegDataType.l
iLength = 256
sDescriptionBuffer = Space(iLength)
iResult = SetupDiGetDeviceRegistryProperty(hDeviceInfoSet, *uSpDevInfoData, #SPDRP_DEVICEDESC, @iPropRegDataType,
@sDescriptionBuffer, iLength, @iLength)
If ((iResult = #ERROR_INVALID_DATA) Or (iResult = 0))
Debug "Error " + iResult +
" GetSerialDescription()->SetupDiGetDeviceRegistryProperty() Can not read registry value PortName for device"
Else
sReturn = sDescriptionBuffer
EndIf
ProcedureReturn sReturn
EndProcedure
Procedure.i GetSerialPortsList(List DeviceInfoList.uDeviceInfo())
Protected iReturn.i, fResult.i
Protected hDeviceInfoSet.i, uSpDevInfoData.uSpDevInfoData, iMemberIndex.l
Protected uGuidDevInterfaceComport.GUID
; DataSection
; GuidDevInterfaceComport:
; Data.l $86E0D1E0
; Data.w $8089, $11D0
; Data.b $9C, $E4, $08, $00, $3E, $30, $1F, $73
; EndDataSection
With uGuidDevInterfaceComport
\Data1 = $86E0D1E0
\Data2 = $8089
\Data3 = $11D0
\Data4[0] = $9C
\Data4[1] = $E4
\Data4[2] = $08
\Data4[3] = $00
\Data4[4] = $3E
\Data4[5] = $30
\Data4[6] = $1F
\Data4[7] = $73
EndWith
hDeviceInfoSet = SetupDiGetClassDevs(@uGuidDevInterfaceComport, #Null, #Null, (#DIGCF_PRESENT | #DIGCF_DEVICEINTERFACE))
fResult = Bool(hDeviceInfoSet <> #INVALID_HANDLE_VALUE)
If Not fResult
hDeviceInfoSet = #Null
Debug "Error GetSerialPortsList()->SetupDiGetClassDevs() Failed to get device information set for the COM ports"
EndIf
If fResult
iMemberIndex = 0
Repeat
ClearStructure(@uSpDevInfoData, uSpDevInfoData)
uSpDevInfoData\cbSize = SizeOf(uSpDevInfoData)
fResult = SetupDiEnumDeviceInfo(hDeviceInfoSet, iMemberIndex, @uSpDevInfoData)
If Not fResult
Break ; No more devices in the device information set.
Else
AddElement(DeviceInfoList())
With DeviceInfoList()
\sName = GetSerialName(hDeviceInfoSet, @uSpDevInfoData)
\sDescription = GetSerialDescription(hDeviceInfoSet, @uSpDevInfoData)
EndWith
EndIf
iMemberIndex + 1
ForEver
fResult = #True
EndIf
If hDeviceInfoSet
SetupDiDestroyDeviceInfoList(hDeviceInfoSet)
EndIf
iReturn = ListSize(DeviceInfoList())
ProcedureReturn iReturn
EndProcedure
; #################
Define iLibNumber.i
NewList DeviceInfoList.uDeviceInfo()
iLibNumber = LibraryInit()
If iLibNumber
Debug "Serial Ports: " + GetSerialPortsList(DeviceInfoList())
ForEach DeviceInfoList()
With DeviceInfoList()
Debug \sName + " - " + \sDescription
EndWith
Next
LibraryExit(iLibNumber)
EndIf
; [12:42:08] Waiting for executable to start...
; [12:42:08] Executable type: Windows - x64 (64bit, Unicode, Thread, Purifier)
; [12:42:08] Executable started.
; [12:42:08] [Debug] Serial Ports: 4
; [12:42:08] [Debug] COM1 - Kommunikationsanschluss
; [12:42:08] [Debug] COM7 - USB Serial Port
; [12:42:08] [Debug] COM8 - USB Serial Port
; [12:42:08] [Debug] COM5 - Prolific USB-to-Serial Comm Port
; [12:42:08] The Program execution has finished.