Archive: Problem with EnumRegValue


Problem with EnumRegValue
  Hi,

by testing my solution for the issue with library.nsh I found another one:

Please correct me if I'm wrong:

EnumRegValue maybe has an error by design. The example in NSIS documentation (2.06) shows that comparing the result to "" can be used as abort criteria for the loop. In reality those empty "registry variable names" are allowed and regularly used. So a key where such a "default value" is set will not be traversed by that EnumRegValue-loop.

I don't know whether the empty variable name is always the first one (last EnumRegValue parameter=0) in the loop.

I know that there probably is a workaround using ReadRegStr and checking the error flag.


Please submit a bug report.


done


Hi stb, you can use this macro to get the number of value

!define RegOpenKey "Advapi32::RegOpenKey(i, t, i) i"
!define RegCloseKey "Advapi32::RegCloseKey(i) i"
!define RegQueryInfoKey "Advapi32::RegQueryInfoKey(i, t, i, i, i, i, i, i, i, i, i, i) i"
!define HKEY_CLASSES_ROOT 0x80000000
!define HKEY_CURRENT_USER 0x80000001
!define HKEY_LOCAL_MACHINE 0x80000002
!define HKEY_USERS 0x80000003
!define HKEY_PERFORMANCE_DATA 0x80000004

!macro GetRegValueNum OUTPUT ROOT KEY
Push `${KEY}`
Push `${ROOT}`
Push $R0
Push $R1
Exch 2
Exch
Exch 3
Exch
System::Call /NOUNLOAD "*(i 0) i .R0"
System::Call /NOUNLOAD "${RegOpenKey}(s, s, R0)"
Push $R0
System::Call /NOUNLOAD "*$R0(&i4 .R0)"
System::Call /NOUNLOAD "*(i 0) i .R1"
System::Call /NOUNLOAD "${RegQueryInfoKey}(R0, i 0, 0, 0, 0, 0, 0, R1, 0, 0, 0, 0)"
System::Call /NOUNLOAD "*$R1(i .s)"
System::Free /NOUNLOAD $R1
System::Call /NOUNLOAD "${RegCloseKey}(R0)"
Exch
Pop $R0
System::Free $R0
Exch
Pop $R1
Exch
Pop $R0
Pop ${OUTPUT}
!macroend

And using like this:
!insertmacro GetRegValueNum $0 ${HKCU} Key
${For} $1 0 $0
;do something
${Next}


Thanks for the macro, bluenet! There are two things:

1. If the key does not exist the error flag should be set and the macro should skip the remaining lines and return 0.
2. I think this should be an internal NSIS command and the example for EnumRegValue should use this new internal command (perhaps named "RegValueCount") instead of "" as stop criteria.


And a "RegKeyCount"? QueryRegKeyInfo may be better.


This looks interesting, I have a need to use something like this.

How do I run this macro ... just exactly what does it do?

Nsis tells me missing section and missing output file?

Thks.


compare this code to the example from manual (4.9.2.6)


!insertmacro GetRegValueNum $3 HKLM Software\Microsoft\Windows\CurrentVersion
StrCpy $0 0
loop:
IntCmp $3 $0 done
EnumRegValue $1 HKLM
Software\Microsoft\Windows\CurrentVersion $0
IntOp $0 $0 + 1
ReadRegStr $2 HKLM Software\Microsoft\Windows\CurrentVersion $1
MessageBox MB_YESNO|MB_ICONQUESTION "$1 = $2$\n$\nMore?" IDYES loop
done:

(not tested yet)

You have to include the !macro part (!defines and !macro...!macroend) somewhere into your script and then you can insert the code lines above in a section/function. Please look at other examples and the nice NSIS manual for basics.

If using LogicLib it simple like this

!include LogicLib.nsh


>!define RegOpenKey "Advapi32::RegOpenKey(i, t, i) i"
>!define RegCloseKey "Advapi32::RegCloseKey(i) i"
>!define RegQueryInfoKey "Advapi32::RegQueryInfoKey(i, t, i, i, i, i, i, i, i, i, i, i) i"
>!define HKCR 0x80000000
>!define HKCU 0x80000001
>!define HKLM 0x80000002
>!define HKU 0x80000003
>!define HKPD 0x80000004

>!macro GetRegValueNum OUTPUT ROOT KEY
Push`${KEY}`
>Push `${ROOT}`
>Push $R0
Push $R1
Exch 2
Exch
Exch 3
Exch
System::Call /NOUNLOAD "*(i 0) i .R0"
>System::Call /NOUNLOAD "${RegOpenKey}(s, s, R0)"
>Push $R0
System::Call /NOUNLOAD "*$R0(&i4 .R0)"
>System::Call /NOUNLOAD "*(i 0) i .R1"
>System::Call /NOUNLOAD "${RegQueryInfoKey}(R0, i 0, 0, 0, 0, 0, 0, R1, 0, 0, 0, 0)"
>System::Call /NOUNLOAD "*$R1(i .s)"
>System::Free /NOUNLOAD $R1
System::Call /NOUNLOAD "${RegCloseKey}(R0)"
>Exch
Pop $R0
System::Free $R0
Exch
Pop $R1
Exch
Pop $R0
Pop${OUTPUT}
!macroend

>!insertmacro GetRegValueNum $0 ${HKLM} "SOFTWARE\Microsoft\Windows\CurrentVersion"
>${For} $1 0 $0
EnumRegValue$2 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion" $1
DetailPrint$2
>${Next}
This code will list all value under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion.
Note that you should use ${HKLM} instead of HKLM in this macro