ModemJunki Posted November 27, 2013 Posted November 27, 2013 The below code works (requires DevCon / Windows 7) - an array of device ID strings and their names comes - but it doesn't seem right to have to manipulate the drive letter strings in the array to "fix them up" as I have done. I need a list of all devices from Devcon (including non-present devices). At the end I will check for both present and non-present devices filtered against a list of known devices so I can see which are unplugged from the computer, but first I am building the list of all devices (plugged in or not). I am doing this workaround because DevCon outputs a list with ":" delimiter and if a filter driver (for some softwares) populates a drive letter they also have ":" in the description. See my comments in the "_RunDevcon" functions for where I do this manipulation. Is there a better/smarter way to do this? expandcollapse popup#include <String.au3> #include <Constants.au3> #include <Array.au3> Global $path_Devcon = @ScriptDir & '\devcon.exe' Global $aRemovable, $strRun, $foundall $foundall = _RunDevcon('"' & $path_Devcon & '" findall *'); the findall means we will see "non present devices" _ArrayDisplay($foundall, "List of devices and their PnP IDs", -1, 0, "", "", "Index|Device String|Device Name") ; Builds a device list using devcon ; by BugFix in 2009 and modified for this script Func _RunDevcon($strRun) Local $data, $dvcn = Run("cmd.exe", @SystemDir, @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD) StdinWrite($dvcn, $strRun & @CRLF) StdinWrite($dvcn) While True $data &= StdoutRead($dvcn) If @error Then ExitLoop Sleep(25) WEnd Local $split = StringSplit($data, @LF) $data = '' For $i = 5 To $split[0] If StringStripWS($split[$i], 8) == '' Then ExitLoop $data &= $split[$i] Dim $devices[1][1] $devices = StringSplit($data, @CRLF) Next _ArrayDelete($devices, $devices[0] - 1); because the last line is "<number> matching device(s) found." $devices[0] = UBound($devices, 1) ;~ Some hoops to jump because Devcon returns a list of devices with ;~ a ":" in their descriptions and the delimiter between the devices is a ":"! $dvstr = _ArrayToString($devices, "'"); split array to string $dvstr_fixed = StringReplace($dvstr, ":", "!", 0, 2); replace the colons with something else $devarray = _String_Split($dvstr, "'", ":"); put all back into an array For $j = 1 To $devarray[0][0] - 1; we remove leading whitespace from second column If $devarray[$j][2] = "\" Then; now we fix the drive letters to have a colon again $Noblank = StringReplace($devarray[$j][1] & ":" & $devarray[$j][2], " ", "", 1) $devarray[$j][1] = $Noblank Else $Noblank = StringReplace($devarray[$j][1], " ", "", 1) $devarray[$j][1] = $Noblank EndIf Next _ArrayDeleteCol($devarray, 2); now we can delete the not-needed column _ArrayDelete($devarray, $devarray[0][0] - 1); we ended up with a blank at the end $devarray[0][0] = UBound($devarray, 1) Return $devarray EndFunc ;==>_RunDevcon ;~ Splits a string into an multidimensional array ;~ By wolf9228 in 2009 Func _String_Split($string, $delimiters1, $delimiters2) $Array1 = StringSplit($string, $delimiters1) Dim $MAXUBound = 0, $OutArray2[1][1] For $i = 1 To $Array1[0] Step 1 $OutArray = StringSplit($Array1[$i], $delimiters2) If $MAXUBound < $OutArray[0] Then ReDim $OutArray2[$i][$OutArray[0]] $MAXUBound = $OutArray[0] Else ReDim $OutArray2[$i][UBound($OutArray2, 2)] EndIf For $j = 1 To $OutArray[0] Step 1 $OutArray2[$i - 1][$j - 1] = $OutArray[$j] Next Next Return $OutArray2 EndFunc ;==>_String_Split ;~ Deletes column from array ;~ By PsaltyDS in 2008 Func _ArrayDeleteCol(ByRef $avWork, $iCol) If Not IsArray($avWork) Then Return SetError(1, 0, 0); Not an array If UBound($avWork, 0) <> 2 Then Return SetError(1, 1, 0); Not a 2D array If ($iCol < 0) Or ($iCol > (UBound($avWork, 2) - 1)) Then Return SetError(1, 2, 0); $iCol out of range If $iCol < UBound($avWork, 2) - 1 Then For $c = $iCol To UBound($avWork, 2) - 2 For $r = 0 To UBound($avWork) - 1 $avWork[$r][$c] = $avWork[$r][$c + 1] Next Next EndIf ReDim $avWork[UBound($avWork)][UBound($avWork, 2) - 1] Return 1 EndFunc ;==>_ArrayDeleteCol Always carry a towel.
kylomas Posted November 27, 2013 Posted November 27, 2013 ModemJunki, On my machine one device called "HTREEROOT0" does not have a description. The below code works (requires DevCon / Windows 7) Are you sure about that? Your code returns 2 devices, in fact there are 251 devices. The output returned uses a ': ' (colon+space) delimiter between the device name and description. Incidentally, some of the device names also have a colon in them. Based on that I would do this... #include <String.au3> #include <Constants.au3> #include <Array.au3> #include <userudfs.au3> Global $path_Devcon = @ScriptDir & '\devcon.exe' Global $aRemovable, $strRun, $foundall $foundall = _RunDevcon('"' & $path_Devcon & '" findall *'); the findall means we will see "non present devices" _ArrayDisplay($foundall, "List of devices and their PnP IDs", -1, 0, "", "", "Index|Device String|Device Name") ; Builds a device list using devcon ; by BugFix in 2009 and modified for this script Func _RunDevcon($strRun) Local $data, $dvcn = Run("cmd.exe", @SystemDir, @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD) StdinWrite($dvcn, $strRun & @CRLF) StdinWrite($dvcn) While True $data &= StdoutRead($dvcn) If @error Then ExitLoop Sleep(25) WEnd local $aData = stringregexp($data,'([\V]+\: [\V]+)',3) local $aRet[ubound($aData)][2] for $1 = 0 to ubound($aData) - 1 $aRet[$1][0] = stringregexpreplace($aData[$1],'([\V]+)\: [\V]+','$1') $aRet[$1][1] = stringregexpreplace($aData[$1],'[\V]+\: ([\V]+)','$1') next return $aRet EndFunc kylomas Forum Rules Procedure for posting code "I like pigs. Dogs look up to us. Cats look down on us. Pigs treat us as equals." - Sir Winston Churchill
ModemJunki Posted November 27, 2013 Author Posted November 27, 2013 (edited) Thank you kylomas, that is a much better implementation. I will have to find time to study regex now. http://xkcd.com/1171/ On my system the original returned the same number of devices as devcon (in a cmd box) did. Edited November 27, 2013 by ModemJunki Always carry a towel.
kylomas Posted November 27, 2013 Posted November 27, 2013 ModemJunki, On my system the original returned the same number of devices as devcon (in a cmd box) did The problem is in the _arraydisplay. When I comment out allof the parameters I get all of the data. I never use the parms so have no idea why I am getting abbreviated output (2 items) with them. SRE Explanation: local $aData = stringregexp($data,'([V]+: [V]+)',3) ( - start capture group [V] - capture all non vertical whitespace chars (everything except line feed, form feed vertical tab and carrige return) + - repeat the previous group/class 1 or more times up to... : - the first colon followed by a space ("" = escape special chars) This effectively eliminates any lines not having a ": " sequence. [V]+ - as before, capture all the rest of the string ) - end capture group ,3 - store each captured group in an array $aRet[$1][0] = stringregexpreplace($aData[$1],'([V]+): [V]+','$1') ([V]+) - capture all non-vertical whitespace characters up to.. : - a colon followed by a space [V]+ - continue matching till end of string ,'$1' - replace the matched string with the capture group $aRet[$1][0] - write the replacement to column 0 of row $1 $aRet[$1][1] = stringregexpreplace($aData[$1],'[V]+: ([V]+)','$1') [V]+ - match all non-vertical whitespace characters up to.. : - a colon followed by a space ([V]+) - cature everything after the colon+space sequence ,'$1' - replace the matched string with the capture group $aRet[$1][1] - write the replacement to column 1 of row $1 kylomas Forum Rules Procedure for posting code "I like pigs. Dogs look up to us. Cats look down on us. Pigs treat us as equals." - Sir Winston Churchill
ModemJunki Posted November 27, 2013 Author Posted November 27, 2013 Interesting - on my system there are two items with no description. These get omitted from the final array with the regexed script. :-( HTREEROOT0 HIDVID_046D&PID_C52B&MI_02&COL038&F5A49A3&0&0002 Always carry a towel.
Solution kylomas Posted November 27, 2013 Solution Posted November 27, 2013 (edited) Interesting - on my system there are two items with no description. These get omitted from the final array with the regexed script. :-( HTREEROOT0 HIDVID_046D&PID_C52B&MI_02&COL038&F5A49A3&0&0002 Is that a problem? edit: if it is then this will get the entries with no description. expandcollapse popup#include <String.au3> #include <Constants.au3> #include <Array.au3> Global $path_Devcon = @ScriptDir & '\devcon.exe' Global $aRemovable, $strRun, $foundall $foundall = _RunDevcon('"' & $path_Devcon & '" findall *'); the findall means we will see "non present devices" _ArrayDisplay($foundall, "List of devices and their PnP IDs", -1, 0, "", "", "Index|Device String|Device Name") ; Builds a device list using devcon ; by BugFix in 2009 and modified for this script Func _RunDevcon($strRun) Local $data, $dvcn = Run("cmd.exe", @SystemDir, @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD) StdinWrite($dvcn, $strRun & @CRLF) StdinWrite($dvcn) While True $data &= StdoutRead($dvcn) If @error Then ExitLoop Sleep(25) WEnd local $aData = stringsplit($data,@crlf,3) local $aRet[ubound($aData)-7][2] for $1 = 4 to ubound($aData) - 4 if stringregexp($adata[$1],'\: ') then $aRet[$1-4][0] = stringregexpreplace($aData[$1],'([\V]+)\: [\V]+','$1') $aRet[$1-4][1] = stringregexpreplace($aData[$1],'[\V]+\: ([\V]+)','$1') Else $aret[$1-4][0] = $adata[$1] endif next return $aRet EndFunc Edited November 27, 2013 by kylomas Forum Rules Procedure for posting code "I like pigs. Dogs look up to us. Cats look down on us. Pigs treat us as equals." - Sir Winston Churchill
kylomas Posted November 27, 2013 Posted November 27, 2013 and in a listview control... expandcollapse popup; *** Start added by AutoIt3Wrapper *** #include <GUIConstantsEx.au3> #include <StaticConstants.au3> ; *** End added by AutoIt3Wrapper *** #include <String.au3> #include <Constants.au3> #include <Array.au3> #include <GuiListView.au3> Global $path_Devcon = @ScriptDir & '\devcon.exe' $foundall = _RunDevcon('"' & $path_Devcon & '" findall *'); the findall means we will see "non present devices" ;_ArrayDisplay($foundall, "List of devices and their PnP IDs", -1, 0, "", "", "Index|Device String|Device Name") #AutoIt3Wrapper_Add_Constants=n local $gui010 = guicreate('DevCon List',1000,700) local $aSize = wingetclientsize($gui010) local $lst010 = guictrlcreatelistview('Device|Description',0,20,$aSize[0],550) guictrlsetbkcolor(-1,$GUI_BKCOLOR_LV_ALTERNATE) for $1 = 0 to ubound($foundall) - 1 GUICtrlCreateListViewItem($foundall[$1][0] & '|' & $foundall[$1][1],$lst010) guictrlsetbkcolor(-1,0xc0f0c0) next for $1= 0 to _GUICtrlListView_GetColumnCount($lst010) _GUICtrlListView_SetColumnWidth( $lst010, $1, ($aSize[0]/ _GUICtrlListView_GetColumnCount($lst010)-8) ) next guisetstate() while 1 switch guigetmsg() case $gui_event_close Exit EndSwitch WEnd ; Builds a device list using devcon ; by BugFix in 2009 and modified for this script Func _RunDevcon($strRun) Local $data, $dvcn = Run("cmd.exe", @SystemDir, @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD) StdinWrite($dvcn, $strRun & @CRLF) StdinWrite($dvcn) While True $data &= StdoutRead($dvcn) If @error Then ExitLoop Sleep(25) WEnd local $aData = stringsplit($data,@crlf,3) local $aRet[ubound($aData)-7][2] for $1 = 4 to ubound($aData) - 4 if stringregexp($adata[$1],'\: ') then $aRet[$1-4][0] = stringregexpreplace($aData[$1],'([\V]+)\: [\V]+','$1') $aRet[$1-4][1] = stringregexpreplace($aData[$1],'[\V]+\: ([\V]+)','$1') Else $aret[$1-4][0] = $adata[$1] endif next return $aRet EndFunc Forum Rules Procedure for posting code "I like pigs. Dogs look up to us. Cats look down on us. Pigs treat us as equals." - Sir Winston Churchill
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