Jump to content

Upgrading script to include wildcard


 Share

Recommended Posts

I have a script that ive used for a long time with no probs

As its grown ive noticed a lot of duplication in the array and i wonder how difficult it would be to upgrade it to include wildcards

Here is a snippet taken from the original script for an e.g.

;~ G
$sRegString = "|GarminExpressTrayApp|GameXN|GameXN (news)|GameXN (update)|GamingWonderland Browser Plugin Loader|GamingWonderland Search Scope Monitor|gmsd_gb_72|gmsd_gb_156|gmsd_gb_326|gmsd_gb_340"
Global $aRegKeys = StringSplit($sRegString, "|")

;~ GameXN*  ; <<<<< examples
;~ GamingWonderland*
;~ gmsd_gb_*

$sRegKey = "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\RunOnce"
For $i = 1 To $aRegKeys[0]
    RegRead($sRegKey, $aRegKeys[$i])
    If @error = 0 Then
        RegDelete($sRegKey, $aRegKeys[$i])
        Sleep(100)
    EndIf
Next

Ive added the examples which would shorten it, bear in mind the g section is 20-30 times the size in the example and overall wildcard would help reduce the read from the array which is getting on for 1500+ items 

Is there a way to add wildcard against that kind of array?

Link to comment
Share on other sites

If I understand what you are asking the answer is an easy one that you probably already know, so you must be looking for a more advanced solution.

But for me when I need a wildcard array feature (often use them for _FileListToArrayRec()) is StringinStr() or StringRegExp()

If your just trying to clean up an array due to duplicates maybe _ArrayUniqe() ?

Link to comment
Share on other sites

5 hours ago, mikell said:

You could try a RegEnum reading to an array and then check each entry using funcs String* or a regex ?

I dont understand the last part, funcs String* etc can you explain ?

5 hours ago, ViciousXUSMC said:

If I understand what you are asking the answer is an easy one that you probably already know, so you must be looking for a more advanced solution.

But for me when I need a wildcard array feature (often use them for _FileListToArrayRec()) is StringinStr() or StringRegExp()

If your just trying to clean up an array due to duplicates maybe _ArrayUniqe() ?

I can make the array easy enough yes

$sRegString = "|GarminExpressTrayApp|GameXN*|GamingWonderland*|gmsd_gb_*"
Global $aRegKeys = StringSplit($sRegString, "|")

Thats fine but the bit i dont understand is how to make the For/Next loop understand that it must search for

gmsd_gb_72|gmsd_gb_156|gmsd_gb_326|gmsd_gb_340"

based upon gmsd_gb_*

Does that make it any clearer?

I just dont get who to integrate wildcard into the function so the function understands to cycle through every version of gmsd_gb_* for eg

as its applied to the regkey

Edited by Chimaera
Link to comment
Share on other sites

Sorry
I was thinking of something like this : list all keys into an array using RegEnumKey, then loop to check each key with a regex : StringRegExp(..., 'gmsd_gb_.*') , 'GameXN.*' etc  or StringInStr(..., 'gmsd_gb_') ...
So in the $sRegString array you can list the prefixes only

Link to comment
Share on other sites

It is not 100% wildcard, but may help you with the duplicates.  It is using a combination of RegEnumKey() and StringInStr() functions.

 

Local $iCount = 0
Local $sRegString = "|GarminExpressTrayApp|GameXN|GamingWonderland|GamingWonderland Search Scope Monitor|gmsd_gb"
;~ Local $sRegString = "|GarminExpressTrayApp|GameXN|GameXN (news)|GameXN (update)|GamingWonderland Browser Plugin Loader|GamingWonderland Search Scope Monitor|gmsd_gb_72|gmsd_gb_156|gmsd_gb_326|gmsd_gb_340"
Global $aRegKeys = StringSplit($sRegString, "|")

;~ GameXN*  ; <<<<< examples
;~ GamingWonderland*
;~ gmsd_gb_*

$sRegKey = "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\RunOnce"
While 1
    $iCount += 1
    $sSubKey = RegEnumKey($sRegKey, $iCount)
    If @error = 0 Then
        For $i = 1 To UBound($aRegKeys) - 1
            If StringInStr(StringLeft($sSubKey, StringLen($aRegKeys[$i])), $aRegKeys[$i]) Then
                RegDelete($sRegKey, $sSubKey)
                Sleep(100)
            EndIf
        Next
    Else
        ExitLoop
    EndIf
WEnd

 

AutoIt Scripts:NetPrinter - Network Printer UtilityRobocopyGUI - GUI interface for M$ robocopy command line
Link to comment
Share on other sites

what the OP needs to enumerate is values, not keys. this is how to check the beginning of the string. to actually check it, change RunOnce to Run:

Global $sBadValuesPrefixList = 'GameXN|GamingWonderland|gmsd_gb_'
Global $aBadValues = StringSplit($sBadValuesPrefixList, '|')
Global $sRegKey = 'HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\RunOnce'
Global $iValue = 0, $sValue = ''

While True
    $iValue += 1
    $sValue = RegEnumVal($sRegKey, $iValue)
    If @error Then ExitLoop
    For $iBadValue = 1 To $aBadValues[0]
        If _StringBeginsWith($sValue, $aBadValues[$iBadValue]) Then
            ConsoleWrite('match: ' & $sValue & ' => ' & $aBadValues[$iBadValue] & '*' & @CRLF) ; RegDelete($sRegKey, $sValue)
            Sleep(100)
        EndIf
    Next
WEnd

Func _StringBeginsWith($sString, $sSubstring)
    If StringLeft($sString, StringLen($sSubstring)) = $sSubstring Then Return True
    Return False
EndFunc   ;==>_StringBeginsWith

 

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

Link to comment
Share on other sites

Well, again if I get what your asking for this may be some help.

#Include <Array.au3>

Global $sFinalResult

$sRegString = "gmsd_gb_72|gmsd_gb_156|gmsd_gb_326|gmsd_gb_340|gmsd_gb_72|gmsd_gb_156|gmsd_gb_326|gmsd_gb_340|test1|test2|test3|test3"
Global $aRegKeys = StringSplit($sRegString, "|")

;Show Array After Split
_ArrayDisplay($aRegKeys)

For $i = $aRegKeys[0] To 1 Step -1
    If NOT StringInStr($aRegKeys[$i],  "gmsd_gb_") Then
        _ArrayDelete($aRegKeys, $i)
    EndIf
Next

;Show Array After Filtering
_ArrayDelete($aRegKeys, 0)
_ArrayDisplay($aRegKeys)

;Remove Duplicates
$aRegKeysUnique = _ArrayUnique($aRegKeys)

;Show Array After Removing Duplicates
_ArrayDelete($aRegKeysUnique, 0)
_ArrayDisplay($aRegKeysUnique)

For $i = 0 to UBound($aRegKeysUnique) -1
    $sFinalResult &= $aRegKeysUnique[$i] & "|"
Next

;Back to String
MsgBox(0, "", $sFinalResult)

StringInStr in a loop or StringRegExp can act as your "wildcard"

I further went and removed any duplicates, and then put it back to a string so it could be written to a registry key.

Link to comment
Share on other sites

Ok thanks for the examples

Danny i tried yours but couldnt seem to get it to delete the value

ViciousXUSMC There are no duplicates the array is the list of the values i need to remove from the Reg key, whilst they are not ll there on all machines it has to remove the ones that are present. The wildcard part is only to reduce the size of the array.

Orbs is on the right path i think

; Orbs
Global $sBadValuesPrefixList = 'GameXN|GamingWonderland|gmsd_gb_'
Global $aBadValues = StringSplit($sBadValuesPrefixList, '|')
Global $sRegKey = 'HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\RunOnce'
Global $iValue = 0, $sValue = ''

While True
    $iValue += 1
    $sValue = RegEnumVal($sRegKey, $iValue)
    If @error Then ExitLoop
    For $iBadValue = 1 To $aBadValues[0]
        If _StringBeginsWith($sValue, $aBadValues[$iBadValue]) Then
            ConsoleWrite('match: ' & $sValue & ' => ' & $aBadValues[$iBadValue] & '*' & @CRLF) ; RegDelete($sRegKey, $sValue)
            RegDelete($sRegKey, $sValue)
            Sleep(100)
        EndIf
    Next
WEnd

Func _StringBeginsWith($sString, $sSubstring)
    If StringLeft($sString, StringLen($sSubstring)) = $sSubstring Then Return True
    Return False
EndFunc   ;==>_StringBeginsWith

The only question i have is i can only get it to delete 1 value then it exits.

If i run it without the RegDelete it shows all values?, i created some fake values for the test

match: gmsd_gb_25 => gmsd_gb_*
match: gmsd_gb_68 => gmsd_gb_*
match: gmsd_gb_88 => gmsd_gb_*
match: gmsd_gb_23 => gmsd_gb_*

I would have thought the For/Next would have gone round for all values, it should work with what little i know so why doesn't it remove all the entries?

Many thanks for the input guys

Link to comment
Share on other sites

my bad. i should have foreseen this.

when you delete a registry value, the enumeration changes and is no longer valid.

what you need to do is let the loop only report the values to be deleted to another array. only when the loop is done, loop that array to delete the values.

EDIT: like this:

Global $sBadValuesPrefixList = 'GameXN|GamingWonderland|gmsd_gb_'
Global $aBadValues = StringSplit($sBadValuesPrefixList, '|')
Global $sRegKey = 'HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\RunOnce'
Global $iValue = 0, $sValue = ''
Global $sBadValuesToDelete = ''

; list values to be deleted
While True
    $iValue += 1
    $sValue = RegEnumVal($sRegKey, $iValue)
    If @error Then ExitLoop
    For $iBadValue = 1 To $aBadValues[0]
        If _StringBeginsWith($sValue, $aBadValues[$iBadValue]) Then
            ConsoleWrite('match: ' & $sValue & ' => ' & $aBadValues[$iBadValue] & '*' & @CRLF)
            $sBadValuesToDelete &= ('|' & $sValue)
            Sleep(100)
        EndIf
    Next
WEnd

; delete them only after listing is done
Global $aBadValuesToDelete = StringSplit($sBadValuesToDelete, '|')
For $iValue = 1 To $aBadValuesToDelete[0]
    If $aBadValuesToDelete[$iValue] <> '' Then ; do not accidentally delete the "(Default)" value
        ConsoleWrite('about to delete: ' & $aBadValuesToDelete[$iValue] & @CRLF)
        ;RegDelete($sRegKey,$aBadValuesToDelete[$iValue])
    EndIf
Next

Func _StringBeginsWith($sString, $sSubstring)
    If StringLeft($sString, StringLen($sSubstring)) = $sSubstring Then Return True
    Return False
EndFunc   ;==>_StringBeginsWith

 

Edited by orbs

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

Link to comment
Share on other sites

I didn't test the RegDelete part in the preview post.  To make it work in my computer I have to add #RequireAdmin and orbs comment "when you delete a registry value, the enumeration changes and is no longer valid. "

 

#RequireAdmin

Local $iCount = 0, $aDeleteKeys = ''
Local $sRegString = "|GarminExpressTrayApp|GameXN|GamingWonderland|gmsd_gb"
;~ Local $sRegString = "|GarminExpressTrayApp|GameXN|GameXN (news)|GameXN (update)|GamingWonderland Browser Plugin Loader|GamingWonderland Search Scope Monitor|gmsd_gb_72|gmsd_gb_156|gmsd_gb_326|gmsd_gb_340"
Global $aRegKeys = StringSplit($sRegString, "|")

;~ GameXN*  ; <<<<< examples
;~ GamingWonderland*
;~ gmsd_gb_*

$sRegKey = "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\RunOnce"
While 1
    $iCount += 1
    $sSubKey = RegEnumKey($sRegKey, $iCount)
    If @error = 0 Then
        For $i = 1 To $aRegKeys[0]
            If StringInStr(StringLeft($sSubKey, StringLen($aRegKeys[$i])), $aRegKeys[$i]) Then $aDeleteKeys &= $sRegKey & '\' & $sSubKey & '|'
        Next
    Else
        ExitLoop
    EndIf
WEnd

If $aDeleteKeys <> '' Then
    $aDeleteKeys = StringSplit(StringTrimRight($aDeleteKeys, 1), '|')
    If IsArray($aDeleteKeys) Then
        For $x = 1 To $aDeleteKeys[0]
            RegDelete($aDeleteKeys[$x])
            Sleep(100)
        Next
    EndIf
EndIf

 

AutoIt Scripts:NetPrinter - Network Printer UtilityRobocopyGUI - GUI interface for M$ robocopy command line
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...