COM-Ports "richtig" enumerieren

Windowsspezifisches Forum , API ,..
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
pickelrobert
Beiträge: 207
Registriert: 09.12.2004 22:09

COM-Ports "richtig" enumerieren

Beitrag von pickelrobert »

Hallo,

bislang habe ich die COM-Ports in einer Schleife versucht zu öffnen, und wenn dies gelang, in eine Liste der "verfügbaren" Ports eingetragen.

Dummerweise fallen so bereits verwendete Ports ungewollt mit heraus, obwohl diese physikalisch existieren.

Wie gehe ich das Problem "korrekt" an?

Danke schon mal.
DePe
Beiträge: 194
Registriert: 26.11.2017 16:17

Re: COM-Ports "richtig" enumerieren

Beitrag von DePe »

Ich mache das über die Registry, das funktioniert getestet von Windows 2000 bis Windows 10.
Ansonst gibt es noch den komplizierteren Weg über die setupapi.dll, da habe ich aber keinen Code bzw. nur für HID-Geräte.

Peter

Code: Alles auswählen

Procedure SearchAndShowSerialPorts()
	; Ermittelt die vorhandenen seriellen Anschlüsse.
	Protected fResult.i, iResult.i
	Protected ihKey.i, ilpcbName, slpName.s, sValue.s, ilType.i, c.i
	#sKeySerialComm = "HARDWARE\DEVICEMAP\SERIALCOMM"
	
	iResult = RegOpenKeyEx_(#HKEY_LOCAL_MACHINE, #sKeySerialComm, 0, #KEY_QUERY_VALUE, @ihKey)
	If Not (iResult = #ERROR_SUCCESS)
		Debug "Es konnte der Registry-Key nicht geöffnet werden: " + #sKeySerialComm
	Else
		slpName = Space(1024)
		
		Repeat
			ilpcbName = 1024
			iResult = RegEnumValue_(ihKey, c, @slpName, @ilpcbName, 0, 0, 0, 0)
			If  Not (iResult = #ERROR_SUCCESS)
				; Kein Fehler, es ist dann kein Eintrag mehr vorhanden zum Einlesen.
				Break
			Else
				sValue = Left(slpName, ilpcbName)
				If sValue = ""
					Break
				EndIf
				ilpcbName = 1024
				ilType = 0
				iResult = RegQueryValueEx_(ihKey, sValue, 0, @ilType, @slpName, @ilpcbName)
				If Not (iResult = #ERROR_SUCCESS)
					Debug "Der Wert von dem Eintrag >" + sValue + "< konnte nicht eingelesen werden."
				Else
				
					Debug slpName	; Ausgabe der seriellen Anschlüsse.
					
				EndIf
				c + 1
			EndIf
		ForEver
		RegCloseKey_(ihKey)
	EndIf
	
EndProcedure

SearchAndShowSerialPorts()
DePe
Beiträge: 194
Registriert: 26.11.2017 16:17

Re: COM-Ports "richtig" enumerieren

Beitrag von DePe »

Hier habe ich noch einen Testcode von mir für die SetupAPI.dll gefunden.

Peter

Die Ausgabe ist z.B.:

Code: Alles auswählen

[Debug] Serial Ports: 3
[Debug] ----------
[Debug] sName: COM1
[Debug] sDescription: Kommunikationsanschluss
[Debug] sManufacturer: (Standardanschlusstypen)
[Debug] sFriendlyName: Kommunikationsanschluss (COM1)
[Debug] ----------
[Debug] sName: COM5
[Debug] sDescription: Prolific USB-to-Serial Comm Port
[Debug] sManufacturer: Prolific
[Debug] sFriendlyName: Prolific USB-to-Serial Comm Port (COM5)
[Debug] ----------
[Debug] sName: COM8
[Debug] sDescription: USB Serial Port
[Debug] sManufacturer: FTDI
[Debug] sFriendlyName: USB Serial Port (COM8)
Testcode:

Code: Alles auswählen

; 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
#SPDRP_MFG = $0B

; // Device registry property codes
; // (Codes marked as read-only (R) may only be used for
; // SetupDiGetDeviceRegistryProperty)
; //
; // These values should cover the same set of registry properties
; // as defined by the CM_DRP codes in cfgmgr32.h.
; //
; // Note that SPDRP codes are zero based while CM_DRP codes are one based!
; //
#SPDRP_DEVICEDESC = $00  ; // DeviceDesc (R/W)
#SPDRP_HARDWAREID = $01  ; // HardwareID (R/W)
#SPDRP_COMPATIBLEIDS = $02  ; // CompatibleIDs (R/W)
#SPDRP_UNUSED0 = $03  ; // unused
#SPDRP_SERVICE = $04  ; // Service (R/W)
#SPDRP_UNUSED1 = $05  ; // unused
#SPDRP_UNUSED2 = $06  ; // unused
#SPDRP_CLASS = $07  ; // Class (R--tied to ClassGUID)
#SPDRP_CLASSGUID = $08  ; // ClassGUID (R/W)
#SPDRP_DRIVER = $09  ; // Driver (R/W)
#SPDRP_CONFIGFLAGS = $0A  ; // ConfigFlags (R/W)
#SPDRP_MFG = $0B  ; // Mfg (R/W)
#SPDRP_FRIENDLYNAME = $0C  ; // FriendlyName (R/W)
#SPDRP_LOCATION_INFORMATION = $0D  ; // LocationInformation (R/W)
#SPDRP_PHYSICAL_DEVICE_OBJECT_NAME = $0E  ; // PhysicalDeviceObjectName (R)
#SPDRP_CAPABILITIES = $0F  ; // Capabilities (R)
#SPDRP_UI_NUMBER = $10  ; // UiNumber (R)
#SPDRP_UPPERFILTERS = $11  ; // UpperFilters (R/W)
#SPDRP_LOWERFILTERS = $12  ; // LowerFilters (R/W)
#SPDRP_BUSTYPEGUID = $13  ; // BusTypeGUID (R)
#SPDRP_LEGACYBUSTYPE = $14  ; // LegacyBusType (R)
#SPDRP_BUSNUMBER = $15  ; // BusNumber (R)
#SPDRP_ENUMERATOR_NAME = $16  ; // Enumerator Name (R)
#SPDRP_SECURITY = $17  ; // Security (R/W, binary form)
#SPDRP_SECURITY_SDS = $18  ; // Security (W, SDS form)
#SPDRP_DEVTYPE = $19  ; // Device Type (R/W)
#SPDRP_EXCLUSIVE = $1A  ; // Device is exclusive-access (R/W)
#SPDRP_CHARACTERISTICS = $1B  ; // Device Characteristics (R/W)
#SPDRP_ADDRESS = $1C  ; // Device Address (R)
#SPDRP_UI_NUMBER_DESC_FORMAT = $1D  ; // UiNumberDescFormat (R/W)
#SPDRP_DEVICE_POWER_DATA = $1E  ; // Device Power Data (R)
#SPDRP_REMOVAL_POLICY = $1F  ; // Removal Policy (R)
#SPDRP_REMOVAL_POLICY_HW_DEFAULT = $20  ; // Hardware Removal Policy (R)
#SPDRP_REMOVAL_POLICY_OVERRIDE = $21  ; // Removal Policy Override (RW)
#SPDRP_INSTALL_STATE = $22  ; // Device Install State (R)
#SPDRP_LOCATION_PATHS = $23  ; // Device Location Paths (R)
#SPDRP_BASE_CONTAINERID = $24  ; // Base ContainerID (R)
;
#SPDRP_MAXIMUM_PROPERTY = $25  ; // Upper bound on ordinals


Structure uDeviceInfo
	sName.s
	; Device registry property.
	sDescription.s
	sHardwareId.s
	sCompatibleIds.s
	sService.s
	sClass.s
	sClassGuid.s
	sDriver.s
	sConfigFlags.s
	sManufacturer.s
	sFriendlyName.s
	sLocationInformation.s
	sPhysicalDeviceObjectName.s
	sCapabilities.s
	sUiNumber.s
	sUpperFilters.s
	sLowerFilters.s
	sBusTypeGuid.s
	sLegacyBusType.s
	sBusNumber.s
	sEnumeratorName.s
	sSecurity.s
	sSecuritySds.s
	sDevType.s
	sExclusive.s
	sCharacteristics.s
	sAddress.s
	sUiNumberDescFormat.s
	sDevicePowerData.s
	sRemovalPolicy.s
	sRemovalPolicyHwDefault.s
	sRemovalPolicyOverride.s
	sInstallState.s
	sLocationPaths.s
	sBaseContainerId.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 GetSerialPortName(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 GetSerialPortProperty(hDeviceInfoSet.i, *uSpDevInfoData.uSpDevInfoData, iPropertyCode.l)
	Protected sReturn.s, iResult.i
	Protected sDescriptionBuffer.s, iLength.l, iPropRegDataType.l
	
	iLength = 256
	sDescriptionBuffer = Space(iLength)
	
	iResult = SetupDiGetDeviceRegistryProperty(hDeviceInfoSet, *uSpDevInfoData, iPropertyCode, @iPropRegDataType,
		 @sDescriptionBuffer, iLength, @iLength)
	If ((iResult = #ERROR_INVALID_DATA) Or (iResult = 0))
		sReturn = "Error " + iResult
		Debug "Error " + iResult +
			" GetSerialDescription()->SetupDiGetDeviceRegistryProperty() Can not read registry value " + iPropertyCode + " 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))
	hDeviceInfoSet = SetupDiGetClassDevs(?GuidDevInterfaceComport, #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 = GetSerialPortName(hDeviceInfoSet, @uSpDevInfoData)

					\sDescription = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_DEVICEDESC)
; 					\sHardwareId = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_HARDWAREID)
; 					\sCompatibleIds = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_COMPATIBLEIDS)
; 					\sService = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_SERVICE)
; 					\sClass = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_CLASS)
; 					\sClassGuid = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_CLASSGUID)
; 					\sDriver = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_DRIVER)
; 					\sConfigFlags = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_CONFIGFLAGS)
					\sManufacturer = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_MFG)
					\sFriendlyName = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_FRIENDLYNAME)
; 					\sLocationInformation = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_LOCATION_INFORMATION)
; 					\sPhysicalDeviceObjectName = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_PHYSICAL_DEVICE_OBJECT_NAME)
; 					\sCapabilities = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_CAPABILITIES)
; 					\sUiNumber = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_UI_NUMBER)
; 					\sUpperFilters = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_UPPERFILTERS)
; 					\sLowerFilters = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_LOWERFILTERS)
; 					\sBusTypeGuid = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_BUSTYPEGUID)
; 					\sLegacyBusType = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_LEGACYBUSTYPE)
; 					\sBusNumber = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_BUSNUMBER)
; 					\sEnumeratorName = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_ENUMERATOR_NAME)
; 					\sSecurity = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_SECURITY)
; 					\sSecuritySds = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_SECURITY_SDS)
; 					\sDevType = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_DEVTYPE)
; 					\sExclusive = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_EXCLUSIVE)
; 					\sCharacteristics = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_CHARACTERISTICS)
; 					\sAddress = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_ADDRESS)
; 					\sUiNumberDescFormat = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_UI_NUMBER_DESC_FORMAT)
; 					\sDevicePowerData = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_DEVICE_POWER_DATA)
; 					\sRemovalPolicy = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_REMOVAL_POLICY)
; 					\sRemovalPolicyHwDefault = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_REMOVAL_POLICY_HW_DEFAULT)
; 					\sRemovalPolicyOverride = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_REMOVAL_POLICY_OVERRIDE)
; 					\sInstallState = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_INSTALL_STATE)
; 					\sLocationPaths = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_LOCATION_PATHS)
; 					\sBaseContainerId = GetSerialPortProperty(hDeviceInfoSet, @uSpDevInfoData, #SPDRP_BASE_CONTAINERID)

				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 "----------"
			Debug "sName: " + \sName
			Debug "sDescription: " + \sDescription
; 			Debug "sHardwareId: " + \sHardwareId
; 			Debug "sCompatibleIds: " + \sCompatibleIds
; 			Debug "sService: " + \sService
; 			Debug "sClass: " + \sClass
; 			Debug "sClassGuid: " + \sClassGuid
; 			Debug "sDriver: " + \sDriver
; 			Debug "sConfigFlags: " + \sConfigFlags
			Debug "sManufacturer: " + \sManufacturer
			Debug "sFriendlyName: " + \sFriendlyName
; 			Debug "sLocationInformation: " + \sLocationInformation
; 			Debug "sPhysicalDeviceObjectName: " + \sPhysicalDeviceObjectName
; 			Debug "sCapabilities: " + \sCapabilities
; 			Debug "sUiNumber: " + \sUiNumber
; 			Debug "sUpperFilters: " + \sUpperFilters
; 			Debug "sLowerFilters: " + \sLowerFilters
; 			Debug "sBusTypeGuid: " + \sBusTypeGuid
; 			Debug "sLegacyBusType: " + \sLegacyBusType
; 			Debug "sBusNumber: " + \sBusNumber
; 			Debug "sEnumeratorName: " + \sEnumeratorName
; 			Debug "sSecurity: " + \sSecurity
; 			Debug "sSecuritySds: " + \sSecuritySds
; 			Debug "sDevType: " + \sDevType
; 			Debug "sExclusive: " + \sExclusive
; 			Debug "sCharacteristics: " + \sCharacteristics
; 			Debug "sAddress: " + \sAddress
; 			Debug "sUiNumberDescFormat: " + \sUiNumberDescFormat
; 			Debug "sDevicePowerData: " + \sDevicePowerData
; 			Debug "sRemovalPolicy: " + \sRemovalPolicy
; 			Debug "sRemovalPolicyHwDefault: " + \sRemovalPolicyHwDefault
; 			Debug "sRemovalPolicyOverride: " + \sRemovalPolicyOverride
; 			Debug "sInstallState: " + \sInstallState
; 			Debug "sLocationPaths: " + \sLocationPaths
; 			Debug "sBaseContainerId: " + \sBaseContainerId
		EndWith
	Next
	
	LibraryExit(iLibNumber)
EndIf
pickelrobert
Beiträge: 207
Registriert: 09.12.2004 22:09

Re: COM-Ports "richtig" enumerieren

Beitrag von pickelrobert »

Danke. Werde es ausprobieren.
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: COM-Ports "richtig" enumerieren

Beitrag von Kiffi »

Es gibt den Kommandozeile-Befehl "mode", der die verfügbaren COM-Ports auflistet.
Mit ein wenig Text-Parsing könnte man sich was aus dem Output zusammenfriemeln:

Code: Alles auswählen

Compiler = RunProgram("cmd.exe", "/c mode", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Hide)
Output = ""
If Compiler
  While ProgramRunning(Compiler)
    If AvailableProgramOutput(Compiler)
      Output + ReadProgramString(Compiler) + Chr(13)
    EndIf
  Wend
  CloseProgram(Compiler)
EndIf
MessageRequester("Output", Output)
Und hier noch eine Lösung, die die ComPorts mittels vbs/wmi ermittelt:

Code: Alles auswählen

EnableExplicit

Structure sComPorts
  Binary.s
  Description.s
  DeviceID.s
  MaxBaudRate.s
  MaximumInputBufferSize.s
  MaximumOutputBufferSize.s
  Name.s
  OSAutoDiscovered.s
  PNPDeviceID.s
  ProviderType.s
  SettableBaudRate.s
  SettableDataBits.s
  SettableFlowControl.s
  SettableParity.s
  SettableParityCheck.s
  SettableRLSD.s
  SettableStopBits.s
  Supports16BitMode.s
  SupportsDTRDSR.s
  SupportsElapsedTimeouts.s
  SupportsIntTimeouts.s
  SupportsParityCheck.s
  SupportsRLSD.s
  SupportsRTSCTS.s
  SupportsSpecialCharacters.s
  SupportsXOnXOff.s
  SupportsXOnXOffSet.s
EndStructure

Global NewList ComPorts.sComPorts()

Procedure EnumerateComPorts()
  
  Protected VbScript.s
  Protected EnumerateSerialPortsFilename.s = GetTemporaryDirectory() + "enumerateSerialPorts.vbs"
  
  ;{-
  
  VbScript = ~"On Error Resume Next" + #CRLF$ + 
             ~"" + #CRLF$ + 
             ~"Dim StdOut : Set StdOut = CreateObject(#DQUOTE$Scripting.FileSystemObject#DQUOTE$).GetStandardStream(1)" + #CRLF$ + 
             ~"" + #CRLF$ + 
             ~"strComputer = #DQUOTE$.#DQUOTE$" + #CRLF$ + 
             ~"Set objWMIService = GetObject(#DQUOTE$winmgmts:#DQUOTE$ & #DQUOTE${impersonationLevel=impersonate}!\\\\#DQUOTE$ & strComputer & #DQUOTE$\\root\\cimv2#DQUOTE$)" + #CRLF$ + 
             ~"" + #CRLF$ + 
             ~"Set colItems = objWMIService.ExecQuery(#DQUOTE$Select * from Win32_SerialPort#DQUOTE$)" + #CRLF$ + 
             ~"" + #CRLF$ + 
             ~"Function TrueOrFalse(value)" + #CRLF$ + 
             ~" If value Then" + #CRLF$ + 
             ~" 	TrueOrFalse = #DQUOTE$true#DQUOTE$" + #CRLF$ + 
             ~" Else" + #CRLF$ + 
             ~" 	TrueOrFalse = #DQUOTE$false#DQUOTE$" + #CRLF$ + 
             ~" End If" + #CRLF$ + 
             ~"End Function" + #CRLF$ + 
             ~"" + #CRLF$ + 
             ~"JsonString = #DQUOTE$[#DQUOTE$" + #CRLF$ + 
             ~"" + #CRLF$ + 
             ~"For Each objItem in colItems" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$ { #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$Binary#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.Binary) & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$Description#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & objItem.Description & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$DeviceID#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & objItem.DeviceID & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$MaxBaudRate#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & objItem.MaxBaudRate & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$MaximumInputBufferSize#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & objItem.MaximumInputBufferSize & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$MaximumOutputBufferSize#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & objItem.MaximumOutputBufferSize & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$Name#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & objItem.Name & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$OSAutoDiscovered#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.OSAutoDiscovered) & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$PNPDeviceID#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & objItem.PNPDeviceID & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$ProviderType#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & objItem.ProviderType & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$SettableBaudRate#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.SettableBaudRate) & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$SettableDataBits#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.SettableDataBits) & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$SettableFlowControl#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.SettableFlowControl) & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$SettableParity#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.SettableParity) & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$SettableParityCheck#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.SettableParityCheck) & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$SettableRLSD#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.SettableRLSD) & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$SettableStopBits#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.SettableStopBits) & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$Supports16BitMode#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.Supports16BitMode) & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$SupportsDTRDSR#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.SupportsDTRDSR) & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$SupportsElapsedTimeouts#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.SupportsElapsedTimeouts) & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$SupportsIntTimeouts#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.SupportsIntTimeouts) & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$SupportsParityCheck#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.SupportsParityCheck) & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$SupportsRLSD#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.SupportsRLSD) & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$SupportsRTSCTS#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.SupportsRTSCTS) & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$SupportsSpecialCharacters#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.SupportsSpecialCharacters) & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$SupportsXOnXOff#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.SupportsXOnXOff) & #DQUOTE$#DQUOTE$#DQUOTE$ , #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$#DQUOTE$#DQUOTE$SupportsXOnXOffSet#DQUOTE$#DQUOTE$: #DQUOTE$#DQUOTE$#DQUOTE$ & TrueOrFalse(objItem.SupportsXOnXOffSet) & #DQUOTE$#DQUOTE$#DQUOTE$ #DQUOTE$" + #CRLF$ + 
             ~"	JsonString = JsonString & #DQUOTE$ }, #DQUOTE$" + #CRLF$ + 
             ~"Next" + #CRLF$ + 
             ~"" + #CRLF$ + 
             ~"JsonString = JsonString & #DQUOTE$]#DQUOTE$" + #CRLF$ + 
             ~"" + #CRLF$ + 
             ~"WScript.Echo JsonString"
  
  ;}-
  
  VbScript = ReplaceString(VbScript, "#DQUOTE$", #DQUOTE$)
  
  Protected FF
  
  FF = CreateFile(#PB_Any, EnumerateSerialPortsFilename)
  If FF
    WriteStringN(FF, VbScript)
    CloseFile(FF)
  EndIf
  
  ; VbScript ausführen und den Output in JsonString eintragen:
  
  Protected Compiler
  Protected JsonString.s
  
  Compiler = RunProgram("cscript", EnumerateSerialPortsFilename, "", #PB_Program_Open | #PB_Program_Read)
  
  If Compiler
    While ProgramRunning(Compiler)
      If AvailableProgramOutput(Compiler)
        JsonString = ReadProgramString(Compiler)
        If Left(JsonString, 1) = "["
          Break
        EndIf
      EndIf
    Wend
    CloseProgram(Compiler)
  EndIf
  
  DeleteFile(EnumerateSerialPortsFilename)
  
  ; JsonString parsen und in eine LinkedList überführen:
    
  JsonString = ReplaceString(JsonString, "}, ]", "} ]")
  JsonString = ReplaceString(JsonString, "\", "\\")
  
  ; Debug JsonString
  
  If ParseJSON(0, JsonString)    
    ExtractJSONList(JSONValue(0), ComPorts())
    FreeJSON(0)
  Else
    Debug JSONErrorMessage()
    Debug JSONErrorLine()
    Debug JSONErrorPosition()
  EndIf
  
EndProcedure

EnumerateComPorts()

ForEach ComPorts()
  Debug "DeviceID: " + ComPorts()\DeviceID
  Debug "MaxBaudRate: " + ComPorts()\MaxBaudRate
  ; ...
Next
a²+b²=mc²
DePe
Beiträge: 194
Registriert: 26.11.2017 16:17

Re: COM-Ports "richtig" enumerieren

Beitrag von DePe »

Hallo Kiffi,

die Version mit 'mode' gibt keine geöffneten Ports aus. Und die VBS/WMI-Version zeigt mir keine USB-Seriell-Adapter an, nur die vorhandenen vom Mainboard.

Peter
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: COM-Ports "richtig" enumerieren

Beitrag von Kiffi »

DePe hat geschrieben: 18.08.2024 19:05die Version mit 'mode' gibt keine geöffneten Ports aus. Und die VBS/WMI-Version zeigt mir keine USB-Seriell-Adapter an, nur die vorhandenen vom Mainboard.
Ach, Mist! Ich selber habe nur COM1. Naja, war'n Versuch wert.
a²+b²=mc²
Antworten