; #FUNCTION# ==================================================================================================================== ; Name ..........: _CommAPI_GetPorts ; Description ...: Get available ports ; Syntax ........: _CommAPI_GetPorts([$vFormat = 0[, $bFilter = True[, $bOnlyCOM = True]]]) ; Parameters ....: $vFormat - [in] Output format (see Modifications). Default: 0 ; $bFilter - [in] Filter out ports without port number (see Modifications). Default: true ; $bOnlyCOM - [in] Only get serial ports. Default: true ; Return values .: Success - A string or array with detected ports (empty string or empty array if no port detected) ; Failure - False ; @error - Line number where SetError called ; Author ........: ¿? ; Modified ......: 20230128 by Javier Perez (see modifications) ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: No ; =============================================================================================================================== ;Modifications: ;- Added starting WMI Service when ObjGet returns error ;- Added output format parameter ($vFormat): ; = 0 (Integer, default) : returns an array (0-based) of integers with each value a port number. Ex: [3, 15] ; = 1 (Integer) : returns an array (0-based) of strings with each value with a port name. Ex: ['COM3', 'COM15'] ; = 2 (Integer) : returns a bidimensional array (0-based). The second dimension has the following elements: ; [0] : String. Port Name. ; [1] : Integer. Port number (for COM3: 3, for LPT1: 1, etc) ; [2] : String. Port type (COM or LPT). ; [3] : String. Hardware ID. ; [4] : String. Manufacturer. ; [5] : String. Description. ; = S (String) : returns a string with port names separated by S (it may be ',', @CRLF, etc). Ex: "COM3,COM15" ;- Added recognizing ports with no COM number assigned. This method also allow to detect LPT ports. * ;- Added $bFilter option to filter out ports without assigned number ;- Added $bOnlyCOM to filter out non COM ports (because of *) ;* : ; - when a port exist but doesn't has an assigned number, the function assign port number 0 and port name XXX0. ; - the detection of unassigned ports allow to detect anormal situations like when Prolific drivers ; detects a cloned USB/Serial interface. In this case, the driver doesn't assign a port number and ; port name has the string "THIS IS NOT PROLIFIC..." Func _CommAPI_GetPorts($vFormat = 0, $bFilter = true, $bOnlyCOM = true) Local Const $wbemFlagForwardOnly = 0x20 ;Causes a forward-only enumerator to be returned. Forward-only enumerators are generally much faster and use less memory than conventional enumerators, but they do not allow calls to SWbemObject.Clone_. Local Const $wbemFlagBidirectional = 0x00 ;Causes WMI to retain pointers to objects of the enumeration until the client releases the enumerator. Local Const $wbemFlagReturnImmediately = 0x10 ;Causes the call to return immediately. Local Const $wbemFlagReturnWhenComplete = 0x00 ;Causes this call to block until the query is complete. This flag calls the method in the synchronous mode. Local Const $wbemQueryFlagPrototype = 0x02 ;Used for prototyping. This flag stops the query from happening and returns an object that looks like a typical result object. Local $vResult, $oWMIService, $oItems, $oItem, $bArray, $sSep, $iPort, $sType, $sPort, $iTemp $bArray = IsNumber($vFormat) If $bArray Then If $vFormat = 2 Then Local $vResult[0][0] Else Local $vResult[0] EndIf Else $vResult = '' $sSep = $vFormat EndIf $oWMIService = ObjGet("winmgmts:\\localhost\root\CIMV2") If @error Then RunWait(@SystemDir & '\sc.exe config winmgmt start= auto', '', @SW_HIDE) RunWait(@ComSpec & ' /c net start winmgmt', '', @SW_HIDE) $oWMIService = ObjGet("winmgmts:\\localhost\root\CIMV2") If @error Then Return SetError(@error, @ScriptLineNumber, False) EndIf $oItems = $oWMIService.ExecQuery("SELECT * FROM Win32_PnPEntity WHERE ClassGuid='{4d36e978-e325-11ce-bfc1-08002be10318}'", "WQL", $wbemFlagReturnWhenComplete) If Not IsObj($oItems) Or $oItems.Count = 0 Then Return $vResult For $oItem In $oItems $iPort = 0 $sType = "XXX" $iTemp = StringInStr($oItem.Name, "(", 1, -1) If $iTemp <> 0 Then $iPort = Number(StringMid($oItem.Name, $iTemp + 4)) $sType = StringMid($oItem.Name, $iTemp + 1, 3) EndIf If $bFilter And $iPort = 0 Then ContinueLoop If $bOnlyCOM And $sType <> "COM" Then ContinueLoop $sPort = $sType & String($iPort) If $bArray Then Switch $vFormat Case 0 ReDim $vResult[UBound($vResult)+1] $vResult[UBound($vResult)-1] = $iPort Case 1 ReDim $vResult[UBound($vResult)+1] $vResult[UBound($vResult)-1] = $sPort Case 2 ReDim $vResult[UBound($vResult)+1][6] $vResult[UBound($vResult)-1][0] = $oItem.Name $vResult[UBound($vResult)-1][1] = $iPort $vResult[UBound($vResult)-1][2] = $sType $vResult[UBound($vResult)-1][3] = $oItem.DeviceID $vResult[UBound($vResult)-1][4] = $oItem.Manufacturer $vResult[UBound($vResult)-1][5] = $oItem.Description EndSwitch Else $vResult &= $sPort & $sSep EndIf Next If Not $bArray Then $vResult = StringLeft($vResult, StringLen($vResult) - StringLen($sSep)) Return $vResult EndFunc