Hello:
I'm using a usb to serial frequently, each time I use Device Manager to know the name of the corresponding serial port "comx". I like to know the com port number programmatically by doing a loop searching all serial ports available and getting the com number of the one described as "Prolific USB-to-Serial Comm Port". Going to the corresponding properties in Device Manager I noticed that the number is included in the "Display Name" property like "Prolific USB-to-Serial Comm Port (COM9)", is it possible to get this "Display Name" property by a call to some Win-api or other.
Thank you
usb-to-serial: how to get associated display name
usb-to-serial: how to get associated display name
PureBasic: Surprisingly simple, diabolically powerful
Re: usb-to-serial: how to get associated display name
It is easy with an object orientated language:
https://stackoverflow.com/questions/283 ... nformation
In PB I would run wmic.exe:
https://stackoverflow.com/questions/283 ... nformation
In PB I would run wmic.exe:
Code: Select all
WMIC.exe path win32_pnpentity where "PNPClass='Ports'" get Caption,Service,ManufacturerCode: Select all
EnableExplicit
Define WMIC.i, Parameter$, Output$
Parameter$ = "path win32_pnpentity where " + #DQUOTE$ + "PNPClass='Ports'" + #DQUOTE$ + " get Caption,Manufacturer"
WMIC = RunProgram("wmic.exe", Parameter$, "", #PB_Program_Open|#PB_Program_Read|#PB_Program_Hide)
If WMIC
While ProgramRunning(WMIC)
If AvailableProgramOutput(WMIC)
Output$ + ReadProgramString(WMIC) + #LF$
EndIf
Wend
CloseProgram(WMIC)
Debug Output$
EndIf
Re: usb-to-serial: how to get associated display name
Amazing, Thank you very much Infratec!!!
Exactly what I'm searching for
Exactly what I'm searching for
PureBasic: Surprisingly simple, diabolically powerful
Re: usb-to-serial: how to get associated display name
As a side note:
As hobby project I'm writing OBD software for motorcycles.
The only really reliable adapters are using chips from FTDI.
With Prolific I (or better: the users) came very often in trouble.
As hobby project I'm writing OBD software for motorcycles.
The only really reliable adapters are using chips from FTDI.
With Prolific I (or better: the users) came very often in trouble.
Re: usb-to-serial: how to get associated display name
I have translated this C# code to PureBasic:
https://nakov.com/blog/2009/05/10/enume ... tion-in-c/
It's just a first try, but the output works here with Windows 7 and PB v6.11 x64.
Peter
https://nakov.com/blog/2009/05/10/enume ... tion-in-c/
It's just a first try, but the output works here with Windows 7 and PB v6.11 x64.
Peter
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.
Last edited by PeDe on Thu May 23, 2024 5:26 pm, edited 1 time in total.
Re: usb-to-serial: how to get associated display name
The devices are already bought by the school where I teach, till now they work correctly.As a side note:
As hobby project I'm writing OBD software for motorcycles.
The only really reliable adapters are using chips from FTDI.
With Prolific I (or better: the users) came very often in trouble.
Thanks for the info
PureBasic: Surprisingly simple, diabolically powerful
Re: usb-to-serial: how to get associated display name
The main problem with OBD is ... timing.
USB is not really a serial protocol. Normally it waits until a buffer is full, then the buffer is send.
But if you have to send single bytes in a specific time, you can get into trouble.
To avoid this the FTDI driver allows to set a maximum delay value, befor the buffer is send.
You can set it to 1ms, then the device behaves (more or less) like a real serial device.
USB is not really a serial protocol. Normally it waits until a buffer is full, then the buffer is send.
But if you have to send single bytes in a specific time, you can get into trouble.
To avoid this the FTDI driver allows to set a maximum delay value, befor the buffer is send.
You can set it to 1ms, then the device behaves (more or less) like a real serial device.
Re: usb-to-serial: how to get associated display name
I'm using the registry for that.
btw. nothing more unconvinient, than tools, which scan the COM ports at start and keep those fixed.
When you connect your COM adapter afterwards you have to restart the tool to find the new COM Port.
Windows has a nice feature, where you get signaled when a new COM port is added/removed, this is what all my (windows) COM port tools are using:
btw. nothing more unconvinient, than tools, which scan the COM ports at start and keep those fixed.
When you connect your COM adapter afterwards you have to restart the tool to find the new COM Port.
Windows has a nice feature, where you get signaled when a new COM port is added/removed, this is what all my (windows) COM port tools are using:
Code: Select all
;use SetWindowCallback(@CallBack_NewDevice()) for your main window
Procedure CallBack_NewDevice(WindowID, Message, wParam, lParam) ;add/delete live connecting USB devices (windows only)
Protected Result, a$, F
Protected *db.DEV_BROADCAST_HDR
Result = #PB_ProcessPureBasicEvents
Select Message
Case #WM_DEVICECHANGE
If wParam = #DBT_DEVICEARRIVAL
*db = lParam
If *db\dbch_devicetype = #DBT_DEVTYP_PORT
a$ = PeekS(*db + 12)
Debug a$ + " arrived!"
F = #True
PushListPosition(AvailableComs())
ForEach AvailableComs()
If AvailableComs() = a$
F = #False
Break
EndIf
Next
If F
AddElement(AvailableComs())
AvailableComs() = a$
EndIf
PopListPosition(AvailableComs())
EndIf
ElseIf wParam = #DBT_DEVICEREMOVECOMPLETE
*db = lParam
If *db\dbch_devicetype = #DBT_DEVTYP_PORT
a$ = PeekS(*db + 12)
Debug a$ + " removed!"
If ListIndex(AvailableComs()) <> - 1 And AvailableComs() = a$
;This was our active Loggerport
CloseSerialPorts()
DeleteElement(AvailableComs())
If ListSize(AvailableComs()) > 0
FirstElement(AvailableComs())
Else
AddElement(AvailableComs())
AvailableComs() = "COM1"
EndIf
Else
;This was something Else...
PushListPosition(AvailableComs())
ForEach AvailableComs()
If AvailableComs() = a$
DeleteElement(AvailableComs())
Break
EndIf
Next
PopListPosition(AvailableComs())
EndIf
EndIf
EndIf
EndSelect
ProcedureReturn Result
EndProcedure
{Home}.:|:.{Dialog Design0R}.:|:.{Codes}.:|:.{History Viewer Online}.:|:.{Send a Beer}


