DanJD Posted February 27, 2023 Posted February 27, 2023 (edited) 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): expandcollapse popup#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 February 28, 2023 by DanJD [Problem solved]
rudi Posted February 27, 2023 Posted February 27, 2023 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!
DanJD Posted February 27, 2023 Author Posted February 27, 2023 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... 😬
Gianni Posted February 27, 2023 Posted February 27, 2023 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 Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....
DanJD Posted February 28, 2023 Author Posted February 28, 2023 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.
DanJD Posted February 28, 2023 Author Posted February 28, 2023 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 😅 expandcollapse popupLocal $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
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now