Page 1 of 1 1
Topic Options
#169155 - 2006-10-10 02:46 PM enumkey in array
vroedie Offline
Fresh Scripter

Registered: 2006-10-05
Posts: 30
Hi,

I'm trying to build a script that will read all values from a registry key and put them in an array. So that I can reuse this array and enumerate all registry keys from below those registry keys.

I have created the following so far, but I can't seem to get it into an array:

Code:


Dim $Indx, $Keyname, $KeyArr
$Indx = 0

While @ERROR = 0
$Keyname = ENUMKEY("HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\", $Indx)
If $Keyname <> ""
? "Name found: $Keyname"
$KeyArr[$Indx] = $Keyname
$Indx = $Indx + 1
Endif
Loop




I took most of this code from the manual, but it was used in an "If, Endif, goto" construction and I'd rather not use goto's in my script.

regards,

jeroen

Top
#169156 - 2006-10-10 04:01 PM Re: enumkey in array
Witto Offline
MM club member
*****

Registered: 2004-09-29
Posts: 1828
Loc: Belgium
Code:

If NOT @LOGONMODE
Break On
Else
Break Off
EndIf
Dim $RC
$RC = SetOption("Explicit","On")
$RC = SetOption("NoVarsInStrings","On")
$RC = SetOption("NoMacrosInStrings","On")
$RC = SetOption("WrapAtEOL","On")

Dim $Indx, $Keyname, $KeyArr[]
$Indx = 0

While @ERROR = 0
$Keyname = EnumKey( "HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\", $Indx)
If $Keyname <> ""
? "Name found: "+$Keyname
ReDim Preserve $KeyArr[$Indx]
$KeyArr[$Indx] = $Keyname
$Indx = $Indx + 1
EndIf
Loop
? "Number of keys found: "+(Ubound($KeyArr)+1)
For Each $Keyname In $KeyArr
? "- "+$Keyname
Next


Top
#169157 - 2006-10-10 04:46 PM Re: enumkey in array
Richard H. Administrator Offline
Administrator
*****

Registered: 2000-01-24
Posts: 4946
Loc: Leatherhead, Surrey, UK
The loop will be better constructed like this, to avoid false positives on the @ERROR test:
Code:
Dim $sKey
$sKey="HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\"

$Keyname = EnumKey( $sKey, $Indx)
While @ERROR = 0
If $Keyname <> ""
? "Name found: "+$Keyname
ReDim Preserve $KeyArr[$Indx]
$KeyArr[$Indx] = $Keyname
$Indx = $Indx + 1
EndIf
$Keyname = EnumKey( $sKey, $Indx)
Loop


Top
#169158 - 2006-10-10 06:44 PM Re: enumkey in array
Witto Offline
MM club member
*****

Registered: 2004-09-29
Posts: 1828
Loc: Belgium
Richard,
I do not think there will be false positives, because when there is no key anymore, $Keyname will be "" and an error will be raised. The last loop will skip the If/EndIf because of the statement:
Code:

If $Keyname <> ""


Don't you think so?

Top
#169159 - 2006-10-10 07:05 PM Re: enumkey in array
NTDOC Administrator Offline
Administrator
*****

Registered: 2000-07-28
Posts: 11623
Loc: CA
There are some pre-scripted UDFs for this.

ARRAYENUMKEY() - Creates an array of names of the subkeys contained in a registry key
http://www.kixtart.org/ubbthreads/showflat.php?Cat=0&Number=81940

ArrayEnumValue() - Creates an array of names of the registry entries contained in a registry key or subkey
http://www.kixtart.org/ubbthreads/showflat.php?Cat=0&Number=81943

Top
#169160 - 2006-10-11 09:40 AM Re: enumkey in array
vroedie Offline
Fresh Scripter

Registered: 2006-10-05
Posts: 30
Hi,

Thanks! Because I'm still learning I would like to know what you did and how you did it. I've got some questions about it, but this is how I interpret your code:

Code:
  

If NOT @LOGONMODE
Break On
Else
Break Off
EndIf

;I do not know the Break option, so I don't know why this is done

Dim $RC
$RC = SetOption("Explicit","On")
$RC = SetOption("NoVarsInStrings","On")
$RC = SetOption("NoMacrosInStrings","On")
$RC = SetOption("WrapAtEOL","On")

Dim $Indx, $Keyname, $KeyArr[] ;the brackets are for the declaration of an array , that's what I missed.

$Indx = 0

While @ERROR = 0
$Keyname = EnumKey( "HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\", $Indx)

If $Keyname <> ""
? "Name found: "+$Keyname
ReDim Preserve $KeyArr[$Indx] ; Here is stated that the values in the array need to be saved
$KeyArr[$Indx] = $Keyname
$Indx = $Indx + 1
EndIf
Loop
? "Number of keys found: "+(Ubound($KeyArr)+1) ;what is the Ubound for? the plus 1 is because the array starts with 0.
For Each $Keyname In $KeyArr ? "- "+$Keyname ; this I can use to rerun the code for any subkeys.
Next



regards,

jeroen

Top
#169161 - 2006-10-11 10:16 AM Re: enumkey in array
vroedie Offline
Fresh Scripter

Registered: 2006-10-05
Posts: 30
And now, if I wanted to create a function out of this (or use an UDF) and I want to reuse the array so I can do the same to the subkeys of the array I just created.

This is what I've got so far (I added the prints so I could see what values the variables got, but It wasn't much):

Code:
 
$MainKey = "HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\"
? $MainKey

$Step1[] = ReadRegArr($MainKey)
? $Step1
For Each $Key in $Step1
$Ind2 = 0
Redim Preserve $Step2[]
$Step2[$Ind2] = ReadRegArr($MainKey + "\" + $Key)
? $Step2
? $Key
$Ind2 = $Ind2 + 1
? $Ind2
Next


Function ReadRegArr($RegKey)

Dim $Indx, $CurrentKeyname, $KeyArr[], $Regkey
$Indx = 0

While @ERROR = 0
$Keyname = ENUMKEY($RegKey, $Indx)
If $Keyname <> ""
? "Name found: $Keyname"
Redim Preserve $KeyArr[$Indx]
$KeyArr[$Indx] = $Keyname
$Indx = $Indx + 1
Endif
Loop
? "Number of keys found: "+(Ubound($KeyArr)+1)
For Each $Keyname In $KeyArr
? "- "+$Keyname
Next

EndFunction



regards,

jeroen

Top
#169162 - 2006-10-11 10:34 AM Re: enumkey in array
Richard H. Administrator Offline
Administrator
*****

Registered: 2000-01-24
Posts: 4946
Loc: Leatherhead, Surrey, UK
Quote:

Richard,
I do not think there will be false positives, because when there is no key anymore, $Keyname will be "" and an error will be raised. The last loop will skip the If/EndIf because of the statement:
Code:
--------------------------------------------------------------------------------

If $Keyname <> ""

--------------------------------------------------------------------------------

Don't you think so?




Yes...and no

While that would work in this specific case there are two problems. The first is that the loop executes one more time that necessary. More importantly is that if the coder adds extra commands then there is a danger of causing a false positive on the error check.

Here is a very simple example. All that I've done is read an entry "FOO" from each of the subkeys. Assume that the entry will exist on some keys but not on others.

Here is the code:
Code:
Break ON
$Key = "HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\"

"Method 1 (fails)"+@CRLF
"----------------"+@CRLF
$Indx=0
While @ERROR = 0
$Keyname = EnumKey($Key, $Indx)
If $Keyname <> ""
"Name found: "+$Keyname+@CRLF
ReDim Preserve $KeyArr[$Indx] ; Here is stated that the values in the array need to be saved
$KeyArr[$Indx] = $Keyname
"Value of 'FOO' in key is: "+ReadValue($Key+"\"+$Keyname,"FOO")+@CRLF
$Indx=$Indx+1
EndIf
Loop

@CRLF
"Method 2 (works)"+@CRLF
"----------------"+@CRLF
$Indx=0
$Keyname = EnumKey($Key, $Indx)
While Not @ERROR
"Name found: "+$Keyname+@CRLF
ReDim Preserve $KeyArr[$Indx] ; Here is stated that the values in the array need to be saved
$KeyArr[$Indx] = $Keyname
"Value of 'FOO' in key is: "+ReadValue($Key+"\"+$Keyname,"FOO")+@CRLF
$Indx=$Indx+1
$Keyname = EnumKey($Key, $Indx)
Loop



And here is the output:
Code:
Method 1 (fails)
----------------
Name found: BACKUP OF Outlook
Value of 'FOO' in key is:

Method 2 (works)
----------------
Name found: BACKUP OF Outlook
Value of 'FOO' in key is:
Name found: Outlook
Value of 'FOO' in key is:
Name found: RH
Value of 'FOO' in key is:



As you can see, the error caused by the missing entry actually causes the loop to exit early in method 1. Method 2 does not suffer from this problem, and in addition does not iterate the loop for the error pass.

For this reason method 2 is recommended, especially for starters. Once you have the habit of coding loops this way you will avoid some of the confusing and hard to find errors that the alternative methods allow.

Top
#169163 - 2006-10-11 01:56 PM Re: enumkey in array
vroedie Offline
Fresh Scripter

Registered: 2006-10-05
Posts: 30
Tnx,

but how can I use the values of an array in an new array? (See my previous example)

regards,

jeroen

Top
#169164 - 2006-10-11 02:43 PM Re: enumkey in array
Richard H. Administrator Offline
Administrator
*****

Registered: 2000-01-24
Posts: 4946
Loc: Leatherhead, Surrey, UK
Like this:
Code:
Break ON
$=SetOption("Explicit","ON")

Dim $sRootKey
$sRootKey="HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\"

Dim $sMain,$sSub,$asMain,$asSub

$asMain=ReadRegArr($sRootKey)
For Each $sMain in $asMain
"Main key: "+$sMain+@CRLF
$asSub=ReadRegArr($sRootKey+"\"+$sMain)
For Each $sSub in $asSub
" Sub key: "+$sSub+@CRLF
Next
Next
Exit 0

Function ReadRegArr($sKey)
Dim $i,$sSubKey

Redim $ReadRegArr[0]

$i=0
$sSubKey=EnumKey($sKey,$i)
While Not @ERROR
ReDim Preserve $ReadRegArr[$i]
$ReadRegArr[$i]=$sSubKey
$i=$i+1
$sSubKey=EnumKey($sKey,$i)
Loop
If @ERROR=259 Exit 0 Else Exit @ERROR EndIf
EndFunction



You could also create a recursive function to load the entire tree, but that is a little more complex and may not fit your needs.

Top
#169165 - 2006-10-11 04:36 PM Re: enumkey in array
Witto Offline
MM club member
*****

Registered: 2004-09-29
Posts: 1828
Loc: Belgium
"Break" is documented in the kix2010.doc. If a KiX script is broken (p.e. via task manager and use of the "End Task" button on the "Applications" tab), the user will be logged of. The Break is Off.
This behaviour of KiXtart is good during logon scripts, but unwanted in (most of the) other cases.
Normally, we want the Break Off during logon scripts and we want the Break On in any other case. So we could write:
Code:

If NOT @LOGONMODE
Break On
EndIf


But maybe, one day, the KiX community and Ruud will decide that Break should be On per default. To be prepared for that switch, I write
Code:

If NOT @LOGONMODE
Break On
Else
Break Off
EndIf


Top
#169166 - 2006-10-11 04:50 PM Re: enumkey in array
Witto Offline
MM club member
*****

Registered: 2004-09-29
Posts: 1828
Loc: Belgium
UBound is also documented in kix2010.doc. It counts the number of elements in an array, starting from 0.
The next code will return 2 for the UBound Function.
Code:

If NOT @LOGONMODE
Break On
Else
Break Off
EndIf
Dim $RC
$RC = SetOption("Explicit","On")
$RC = SetOption("NoVarsInStrings","On")
$RC = SetOption("NoMacrosInStrings","On")
$RC = SetOption("WrapAtEOL","On")

Dim $arrElements
$arrElements = "One","Two","Three"
? Ubound($arrElements)
For $rc = 0 to Ubound($arrElements)
? "- "+$RC+": "+$arrElements[$RC]
Next


Top
#169167 - 2006-10-11 04:58 PM Re: enumkey in array
vroedie Offline
Fresh Scripter

Registered: 2006-10-05
Posts: 30
Hi,

Great this was exectly what I was looking for, thanks!

I've adjusted the code and function so it can read multiple registry entries, their sub entries, their value's and their value data.

Code:

Break ON
$=SetOption("Explicit","ON")

If RedirectOutput("test.txt") = 0
EndIf

Dim $sRootKey
$sRootKey="HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\"

Dim $sMain,$sSub,$asMain,$asSub,$sSub2,$asSub2,$Val

$asMain=ReadRegArr($sRootKey)
For Each $sMain in $asMain
;"Main key: "+$sMain+@CRLF
$asSub=ReadRegArr($sRootKey+"\"+$sMain)
For Each $sSub in $asSub
;" Sub key: "+$sSub+@CRLF
$asSub2=ReadRegValArr($sRootKey+"\"+$sMain+"\"+$sSub)
For Each $sSub2 in $asSub2
;" sub - Sub key: "+$sSub2+@CRLF
$Val = ReadValue($sRootKey+"\"+$sMain+"\"+$sSub, $sSub2)
If INSTR($Val,".pst")
? "Value data: " + $Val+@CRLF
EndIf
Next
Next
Next
Exit 0

Function ReadRegArr($sKey)
Dim $i,$sSubKey

Redim $ReadRegArr[0]

$i=0
$sSubKey=EnumKey($sKey,$i)
While Not @ERROR
ReDim Preserve $ReadRegArr[$i]
$ReadRegArr[$i]=$sSubKey
$i=$i+1
$sSubKey=EnumKey($sKey,$i)
Loop
If @ERROR=259 Exit 0 Else Exit @ERROR EndIf
EndFunction

Function ReadRegValArr($sVKey)
Dim $iV,$sVSubKey

Redim $ReadRegValArr[0]

$iV=0
$sVSubKey=EnumValue($sVKey,$iV)
While Not @ERROR
ReDim Preserve $ReadRegValArr[$iV]
$ReadRegValArr[$iV]=$sVSubKey
$iV=$iV+1
$sVSubKey=EnumValue($sVKey,$iV)
Loop
If @ERROR=259 Exit 0 Else Exit @ERROR EndIf
EndFunction

Function ReadRegValArr2($sV2Key,$sV2Value)
Dim $iV2,$sV2SubKey

Redim $ReadRegValArr2[0]

$iV2=0
$sV2SubKey=ReadValue($sV2Key,$iV2)
While Not @ERROR
ReDim Preserve $ReadRegValArr2[$iV2]
$ReadRegValArr2[$iV2]=$sV2SubKey
$iV2=$iV2+1
$sV2SubKey=ReadValue($sV2Key,$iV2)
Loop
If @ERROR=259 Exit 0 Else Exit @ERROR EndIf
EndFunction



So if someone can use this, it works!

regards,

jeroen

Top
Page 1 of 1 1


Moderator:  Jochen, Allen, Radimus, Glenn Barnas, ShaneEP, Ruud van Velsen, Arend_, Mart 
Hop to:
Shout Box

Who's Online
1 registered (Allen) and 466 anonymous users online.
Newest Members
gespanntleuchten, DaveatAdvanced, Paulo_Alves, UsTaaa, xxJJxx
17864 Registered Users

Generated in 0.135 seconds in which 0.105 seconds were spent on a total of 12 queries. Zlib compression enabled.

Search the board with:
superb Board Search
or try with google:
Google
Web kixtart.org