Jump to content

[SOLVED] _ArrayDelete based on outcome of separate 'If...Then'?


DanJD
 Share

Recommended Posts

Hi,

 

I am writing an AutoIt script using martin's very helpful Serial Port / COM Port UDF, to try to accomplish these steps in the following order:

1. Display the array generated by _ComGetPortNames()

2. Connect to the port that a device "USB Serial Port" is linked with [using CommSetPort()]

 

However, if I have more than one "USB Serial Port" device connected to my PC, I need to be able to connect to one with a particular VID & PID combination (0403 & 6001 respectively, so this would add a couple steps in between the ones listed above:

2. Search for USB Serial devices that might have a matching VID but different PID 

3. Find the COM ports these are connected to and delete row(s) of the array based on if the COM# matches. 

4. Display new array with the one [required] USB serial device remaining.

5. (was #2) Connect to the [one remaining] port that a device "USB Serial Port" is linked with [using CommSetPort()]

 

Unfortunately I cannot find a way to make this work yet... Can anybody point me in the correct direction please? This is my code so far (please excuse):

 

#include <Constants.au3>
#include <CommMG.au3>
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPIFiles.au3>
#include <Array.au3>

Local $aComPort = _ComGetPortNames()

_ArrayDisplay($aComPort, "BEFORE deleting") ; Initiates the array display showing all active comports before removing any USB serial devices we don't want
$wbemFlagReturnImmediately = "&h10" ; required for WMI 
$wbemFlagForwardOnly = "&h20" ; required for WMI
$WMI = ObjGet("winmgmts:\\" & @ComputerName & "\root\WMI")  ; Retrieving Info from WMI
$aItems = $WMI.ExecQuery("SELECT * FROM MSSerial_PortName", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly) ; Getting Serial port info from WMI
Local $sComPort, $element ; Declaring variables

For $element In $aItems ; https://www.autoitscript.com/forum/topic/151495-find-com-port-in-wmi-based-on-vid-and-pid/
If StringInStr($element.InstanceName, "VID_0403") And Not StringInStr($element.InstanceName, "PID_6001") Then
    $element.PortName = $sDeleteThisPort
    EndIf
Next


$iComToRemove = _ArraySearch($aComPort, $sDeleteThisPort, 0, 0, 0, 1) ; Then search the array for this value (1st parameter after the array name)
    If Not @error Then
        _ArrayDelete($aComPort, $iComToRemove) ; Delete that row of the array if the value to delete e.g. COM5 exists
    EndIf


Local $iIndex = _ArraySearch($aComPort, "USB Serial Port", 0, 0, 0, 0, 1, 3) ; Searches the first array for any connected device named "USB Serial Port" and sets the index value for $iIndex
    If @error Then 
        MsgBox(16, "Error!", "USB Serial Port device not found")  ; Returns error message if there is no USB serial port device connected to the PC
        Exit
    Else
        $sComPort = _ArrayToString($aComPort, Default, $iIndex, $iIndex, Default, 0, 0) ; Labels the matching row in the array as a string value $sComPort
    EndIf
    
    _ArrayDisplay($aComPort, "AFTER deleting")
    Local $iIndex = _ArraySearch($aComPort, "USB Serial Port", 0, 0, 0, 0, 1, 3)
    If @error Then 
        MsgBox(16, "Error!", "USB Serial Port device not found") 
        Exit
        Else
    $sComPort = _ArrayToString($aComPort, Default, $iIndex, $iIndex, Default, 0, 0)
    $sComPortNumber = StringRight($sComPort, 1) ;       This string value (sComPortNumber) gives us just the number of the required ComPort
    EndIf
    
If @error Then
    MsgBox(16, "Error " & @error, "No matching COM port found.")
Else
    Sleep(10)
EndIf

Global $CMPort = $sComPortNumber 
Global $CmBoBaud = 9600
Global $sportSetError = ''
Global $CmboDataBits = 8
Global $CmBoParity = 0
Global $CmBoStop = 1
Global $setflow = 2

_CommSetPort($CMPort, $sportSetError, $CmBoBaud, $CmboDataBits, $CmBoParity, $CmBoStop, $setflow, 3, 2) 

If @error Then
    MsgBox(16, "Error!", "Can't connect to port - " & $CMPort)
    Exit
Else 
    MsgBox(1, "Connection successful", "Succesfully connected to " & "COM " & $CMPort) 
EndIf

 

Edited by DanJD
[Problem solved]
Link to comment
Share on other sites

Hi.

I cannot check your code, as it crashes on my PC

$aItems = $WMI.ExecQuery("SELECT * FROM MSSerial_PortName", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
$aItems = $WMI^ ERROR

Try this approach:

$DevVID="VID_0403"
$DevPID="PID_6001"
If StringInStr($element.InstanceName,$DevVID) Then ; Vendor is good
    if StringInStr($element.InstanceName, "PID_6001") Then ; device is fine
        ; leave it
    Else
        ; remove it
    EndIf
EndIf

 

Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Link to comment
Share on other sites

Hi, 

Thank you for the response - unfortunately I'm still having no luck with deleting the unwanted row in the array even with your solution:

Dim $sDeleteThisPort

For $element In $aItems ; https://www.autoitscript.com/forum/topic/151495-find-com-port-in-wmi-based-on-vid-and-pid/
If StringInStr($element.InstanceName,$DevVID) Then ; Vendor is good
    if StringInStr($element.InstanceName, "PID_6001") Then ; device is fine
        Sleep(50); leave it
    Else 
    $element.PortName = $sDeleteThisPort
    EndIf
EndIf
Next

$iComToRemove = _ArraySearch($aComPort, $sDeleteThisPort, 0, 0, 0, 1) ; Then search the array for this value (1st parameter after the array name)
    If Not @error Then
        _ArrayDelete($aComPort, $iComToRemove) ; Delete that row of the array if the value to delete e.g. COM5 exists
    EndIf

It seems like trying to rename a "$element.PortName" taken from the WMI data to a string like $sDeleteThisPort doesn't work for then trying to remove a row of my $aComPort array isn't going to work. Suggestions for alternative approaches welcome... 😬

Link to comment
Share on other sites

8 hours ago, rudi said:

Hi.

I cannot check your code, as it crashes on my PC

$aItems = $WMI.ExecQuery("SELECT * FROM MSSerial_PortName", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
$aItems = $WMI^ ERROR

 

change lines 12 and 13 from this

$wbemFlagReturnImmediately = "&h10" ; required for WMI
$wbemFlagForwardOnly = "&h20" ; required for WMI

to this

$wbemFlagReturnImmediately = 0x10 ; required for WMI
$wbemFlagForwardOnly = 0x20 ; required for WMI

 

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

After a lot of forum post reading and changing my script around, I have come to the conclusion that trying to set the value of the variable $sDeleteThisPort inside of a 'For...Next' loop is causing the issue. 

Does anyone know of a workaround? Or perhaps a way to display the PID & VID in the original array? My knowledge of WMI is well, non-existent, but I will try to find a way to get these values to display.

Thanks.

Link to comment
Share on other sites

4 hours ago, DanJD said:

After a lot of forum post reading and changing my script around, I have come to the conclusion that trying to set the value of the variable $sDeleteThisPort inside of a 'For...Next' loop is causing the issue. 

Does anyone know of a workaround? Or perhaps a way to display the PID & VID in the original array? My knowledge of WMI is well, non-existent, but I will try to find a way to get these values to display.

Thanks.

 

Figured it out guys 😅

 

Local $aComPort = _ComGetPortNames()

_ArrayDisplay($aComPort, "BEFORE deleting") ; Initiates the array display showing all active comports before removing any USB serial devices we don't want
$wbemFlagReturnImmediately = "&h10" ; required for WMI 
$wbemFlagForwardOnly = "&h20" ; required for WMI
$WMI = ObjGet("winmgmts:\\" & @ComputerName & "\root\WMI")  ; Retrieving Info from WMI
$aItems = $WMI.ExecQuery("SELECT * FROM MSSerial_PortName", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly) ; Getting Serial port info from WMI
Local $sComPort, $element ; Declaring variables


    $Output=""
    $objWMIService = ObjGet("winmgmts:\\localhost\root\WMI")
    $wbemFlagReturnImmediately = "0x10" ; required for WMI 
$wbemFlagForwardOnly = "0x20"
    $aIdents = $objWMIService.ExecQuery("SELECT * FROM MSSerial_PortName WHERE InstanceName LIKE '%VID_0403%' AND NOT InstanceName LIKE '%PID_6001%' ", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
    
Body()

Local $iComToRemove

Func Body()
If IsObj($aIdents) Then
  For $objItem In $aIdents
   ConsoleWrite ($Output) ; output should be COM5
   $Output = StringTrimRight($objItem.PortName, 0) ; 
    $Output = "" & StringTrimLeft($Output, StringInStr($Output, "\", 2, -1))
    $iComToRemove = _ArraySearch($aComPort, $Output, 0, 0, 0, 2) ; Then search the array for this value (1st parameter after the array name)
    If Not @error Then
        _ArrayDelete($aComPort, $iComToRemove) ; Delete that row of the array if the value to delete e.g. COM5 exists
    EndIf
Next
Else 
    MsgBox(1, "WMI OUTPUT", "No objects found in $aIdents")
    EndIf
EndFunc


 _ArrayDisplay($aComPort, "AFTER deleting")
Local $iIndex = _ArraySearch($aComPort, "USB Serial Port", 0, 0, 0, 0, 1, 3) ; Searches the first array for any connected device named "USB Serial Port" and sets the index value for $iIndex
    If @error Then 
        MsgBox(16, "Error!", "USB Serial Port device not found")  ; Returns error message if there is no USB serial port device connected to the PC
        Exit
    Else
        $sComPort = _ArrayToString($aComPort, Default, $iIndex, $iIndex, Default, 0, 0) ; Labels the matching row in the array as a string value $sComPort
        $sComPortNumber = StringRight($sComPort, 1) ;       This string value (sComPortNumber) gives us just the number of the required ComPort
    EndIf
    
    
If @error Then
    MsgBox(16, "Error " & @error, "No matching COM port found.")
Else
    Sleep(10)
EndIf

Global $CMPort = $sComPortNumber 
Global $CmBoBaud = 9600
Global $sportSetError = ''
Global $CmboDataBits = 8
Global $CmBoParity = 0
Global $CmBoStop = 1
Global $setflow = 2

_CommSetPort($CMPort, $sportSetError, $CmBoBaud, $CmboDataBits, $CmBoParity, $CmBoStop, $setflow, 3, 2) 

If @error Then
    MsgBox(16, "Error!", "Can't connect to port - " & $CMPort)
    Exit
Else 
    MsgBox(1, "Connection successful", "Succesfully connected to " & "COM " & $CMPort) 
EndIf

Hope this will help others :) 

DanJD

Link to comment
Share on other sites

  • DanJD changed the title to [SOLVED] _ArrayDelete based on outcome of separate 'If...Then'?

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...