Jump to content

Search through array and delete elements with wildcard (Resolved)


Recommended Posts

  • Moderators

I have a script I've been working on for a while (with the generous help of this forum) that enumerates the applications in Add/Remove Programs on a remote machine. It basically takes the contents of HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall and puts them into an array, as shown in the picture. The code I have is below, and it works well:

<BR>#include <Array.au3><BR><BR><BR>AutoItSetOption("WinTitleMatchMode", 2)<BR>$Computer = InputBox("Enumerate Remote Applications", "Please enter the computer you'd like to connect to.")<BR><BR>$addremove = _SoftwareInfo()<BR>_ArraySort($addremove)<BR>_ArrayDisplay($addremove, 'Add/Remove Entries for ' & $Computer & '.')<BR><BR>Func _SoftwareInfo($s_RemoteComputer = $Computer)<BR>    Local $Count = 1<BR>        <BR>    If $s_RemoteComputer <> '' Then $s_RemoteComputer = '\\' & StringReplace($s_RemoteComputer, '\', '') & '\'      <BR>    Local Const $regkey = $s_RemoteComputer & 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall'<BR>    <BR>    While 1<BR>        $key = RegEnumKey ($regkey, $Count)<BR>        If @error <> 0 then ExitLoop<BR>        $line = RegRead ($regkey & '\' & $key, 'Displayname')<BR>        $line = StringReplace ($line, ' (remove only)', '')<BR><BR>        If $line <> '' Then<BR>            If Not IsDeclared('avArray') Then Dim $avArray[1]<BR>            ReDim $avArray[UBound($avArray) + 1]<BR>            $avArray[UBound($avArray) - 1] = $line<BR>        EndIf<BR>        $Count = $Count + 1<BR>WEnd<BR><BR>    If Not IsDeclared('avArray') Or Not IsArray($avArray) Then<BR>        Return(SetError(1, 0, ''))     <BR>    Else<BR>        $avArray[0] = UBound($avArray) - 1<BR>        Return(SetError(0,0, $avArray))<BR>    EndIf<BR>EndFunc<BR>

I have a couple of things I've been trying to do to enhance this, and am hoping someone can steer me in the right direction. Firstly, I have been attempting to search through the array before displaying it, and remove any reference to MS Updates. I've tried a number of ways with _ArraySearch, _ArrayFindAll, and _ArrayDelete, but I keep missing the mark. The code below seems to come closest, but it deletes every element prior to $string, rather than each instance of it. If anyone can shed some light on the correct syntax, I would appreciate it.

<BR>For $element in $addremove<BR>$string = "Security Update for "<BR>If $element >= $string Then<BR>  _ArrayDelete($addremove, $element)<BR>EndIf<BR>Next<BR>

The second item is less important, just more of how to configure the array window. As the screenshot shows, the array comes up in the default size, and you have to resize it to view properly. I searched through the forums and located a thread where someone suggested making a copy of array.au3, renaming it to arraycustom.au3, and then modifying the _ArrayDisplay function to suit your needs. I have done the same, and it seems to be working (mostly). I simply changed the $iWidth variable to "@DesktopWidth / 2" and the $iHeight variable to "@DesktopHeight - 50". This works well for the height, I can get it to display exactly as I need. The width, however, does not change, regardless of what I put in there. Just curious if there is some boundary that is keeping it from resizing.

Again, the second item is so less important than the first. If anyone has thoughts or (constructive) criticism on either, I would appreciate it.

Edited by JLogan3o13

"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Link to comment
Share on other sites

JLogano3013,

"If $element >= $string Then" means that if the array element is greater than or equal to the string value then...

Change to "If $element = $string Then" and see what you get.

kylomas

Edit: arraydisplay

You might try doing something with $sheader (optional parm for arraydisplay). Possibly: " $sheader = ' ',' ', " etc.

Edit2: Your post title references "wildcard" but I do NOT see any other references to it.

Edited 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

Link to comment
Share on other sites

I have updated your original script to include the deletion of the security updates. You should always delete array elements while looping through the array from the end to the start, never the other way around.

I have also included an update to the Zero element of the $addremove array to keep track of how many items are in the list. Plus, when doing the _ArraySort you should start from the first index to avoid sorting the zeroth element by accident, I have a program called µtorrent and that first character causes it to be placed before the uninstall items.

#include <Array.au3>
AutoItSetOption("WinTitleMatchMode", 2)
$Computer = InputBox("Enumerate Remote Applications", "Please enter the computer you'd like to connect to.")
$addremove = _SoftwareInfo()
For $element = UBound($addremove) - 1 To 1 Step -1
    $string = "Security Update for "
    If StringMid($addremove[$element], 1, StringLen($String)) = $string Then
        _ArrayDelete($addremove, $element)
    EndIf
Next
$addremove[0] = UBound($addremove) - 1
_ArraySort($addremove, 0, 1)
_ArrayDisplay($addremove, 'Add/Remove Entries for ' & $Computer & '.')
Func _SoftwareInfo($s_RemoteComputer = $Computer)
    Local $Count = 1
    If $s_RemoteComputer <> '' Then $s_RemoteComputer = '\\' & StringReplace($s_RemoteComputer, '\', '') & '\'
    Local Const $regkey = $s_RemoteComputer & 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall'
    While 1
        $key = RegEnumKey($regkey, $Count)
        If @error <> 0 Then ExitLoop
        $line = RegRead($regkey & '\' & $key, 'Displayname')
;~      $line = StringReplace($line, ' (remove only)', '')
        If $line <> '' Then
            If Not IsDeclared('avArray') Then Dim $avArray[1]
            ReDim $avArray[UBound($avArray) + 1]
            $avArray[UBound($avArray) - 1] = $line
        EndIf
        $Count = $Count + 1
    WEnd
    If Not IsDeclared('avArray') Or Not IsArray($avArray) Then
        Return (SetError(1, 0, ''))
    Else
        $avArray[0] = UBound($avArray) - 1
        Return (SetError(0, 0, $avArray))
    EndIf
EndFunc   ;==>_SoftwareInfo

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

or just dont add them in the first place

with brewmans code:

edit** I think i see what you were saying about utorrent, as i believe its the same for stripping 7zip, what exactly is causing that?

#include <Array.au3>
AutoItSetOption("WinTitleMatchMode", 2)
$Computer = InputBox("Enumerate Remote Applications", "Please enter the computer you'd like to connect to.")
$addremove = _SoftwareInfo()
_ArraySort ($addremove)
_ArrayDisplay($addremove, 'Add/Remove Entries for ' & $Computer & '.')

Func _SoftwareInfo($s_RemoteComputer = $Computer)
    Local $Count = 1
    If $s_RemoteComputer <> '' Then $s_RemoteComputer = '\\' & StringReplace($s_RemoteComputer, '\', '') & '\'
    Local Const $regkey = $s_RemoteComputer & 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall'
    While 1
        $key = RegEnumKey($regkey, $Count)
        If @error <> 0 Then ExitLoop
        $line = RegRead($regkey & '\' & $key, 'Displayname')
;~      $line = StringReplace($line, ' (remove only)', '')
        If $line <> ''  Then
            If $line = stringinstr($line , "Security Update for") Then
            If Not IsDeclared('avArray') Then Dim $avArray[1]
            ReDim $avArray[UBound($avArray) + 1]
            $avArray[UBound($avArray) - 1] = $line
        EndIf
        Endif
        $Count = $Count + 1
    WEnd
    If Not IsDeclared('avArray') Or Not IsArray($avArray) Then
        Return (SetError(1, 0, ''))
    Else
        $avArray[0] = UBound($avArray) - 1
        Return (SetError(0, 0, $avArray))
    EndIf
EndFunc   ;==>_SoftwareInfo
Edited by iamtheky

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Link to comment
Share on other sites

Another update that avoids adding the entries for Security Updates as iamthekey suggested, but without doing a ReDim every line. This shaved nearly 50% off the run time by avoiding using ReDim and nearly 75% off of the way I was doing it with the ArrayDelete.

The way that the search was being done in the code that iamthekey posted was causing 7Zip to be skipped, luckily I have 7zip installed on this computer so I could see the issue, and I figured out how to avoid that by doing a string to string comparison rather than having it do a number to string comparison which is never a good idea from what I've seen.

So it's kind of a mish-mash between our two tries at this.

#include <Array.au3>
AutoItSetOption("WinTitleMatchMode", 2)
$Timer = TimerInit()
$Computer = InputBox("Enumerate Remote Applications", "Please enter the computer you'd like to connect to.")
$Timer = TimerInit()
$addremove = _SoftwareInfo()
_ArraySort($addremove, 0, 1)
$Diff = TimerDiff($Timer)
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $Diff = ' & $Diff & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
_ArrayDisplay($addremove, 'Add/Remove Entries for ' & $Computer & '.')
Func _SoftwareInfo($s_RemoteComputer = $Computer)
    Local $Count = 1, $Count1 = 1
    If $s_RemoteComputer <> '' Then $s_RemoteComputer = '\\' & StringReplace($s_RemoteComputer, '\', '') & '\'
    Local Const $regkey = $s_RemoteComputer & 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall'
    While 1
        $key = RegEnumKey($regkey, $Count1)
        If @error <> 0 Then ExitLoop
        $line = RegRead($regkey & '\' & $key, 'Displayname')
;~      $line = StringReplace($line, ' (remove only)', '')
        If $line <> '' Then
            If StringMid($line, 1, 19) <> "Security Update for" Then
;~          If $line = StringInStr($line, "Security Update for") Then
                If Not IsDeclared('avArray') Then Dim $avArray[100]
                If UBound($avArray) - $Count <= 1 Then ReDim $avArray[UBound($avArray) + 100]
                $avArray[$Count] = $line
                $Count = $Count + 1
            EndIf
        EndIf
        $Count1 += 1
    WEnd
    If Not IsDeclared('avArray') Or Not IsArray($avArray) Then
        Return (SetError(1, 0, ''))
    Else
        ReDim $avArray[$Count - 1]
        $avArray[0] = UBound($avArray) - 1
        Return (SetError(0, 0, $avArray))
    EndIf
EndFunc   ;==>_SoftwareInfo

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

An easy way to delete elements from an array without using ReDim (very slow) is to duplicate the array, loop through the second one and delete from the first. When you are finished you just empty the second array

$aArray2 = $aArray
For $i= 1 To UBound($aArray2) -1
   If <condition> Then _ArrayDelete($aArray, $i) ; There may be a better method to delete it but my mind is asleep
Next
$aArray2 = ""

I seem to recall that _ArrayDelete uses ReDim so using it there is bad enough without using it again

Another way is to convert the array to a string and then use StringReplace(). There are a few ways to skin the kitty with this one.

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

  • Moderators

Many thanks to all of you for the help. The combination of your assistance gave me just what I was looking for, and will make this 100% better for those using the script. Thanks again.

"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Link to comment
Share on other sites

I only used ReDim, in my last example, when I had to add items to the array and then only once every 100 items. The final ReDim was to trim off the excess blank elements that would be left over after the loop had finished. It minimizes the impact of using ReDim in the script, and I didn't have to use _ArrayDelete at all.

@GEOSoft

Wouldn't you want to loop through the array backwards when you're deleting elements from it? Otherwise you end up with an out of bounds error, and you delete the wrong items.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

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...