- NSIS Discussion
- EnumRegValue search question on unknown subfolders
Archive: EnumRegValue search question on unknown subfolders
bd2005
8th April 2005 08:20 UTC
EnumRegValue search question on unknown subfolders
Ok.
I'm able to search EnumRegValue with known full path.
However, I need to search from "...Windows\CurrentVersions\" to find the "DisplayName" of the Uninstall Program I'm looking for.
This particular Program is .msi installation package and upon installation creates product numbering of which I won't know on many machine of what this product numbering is.
So, my thoughts is to search the registry from one starting point and drill downward to find the "DisplayName" to compare, upon match, then extract the full "copy key name" of the path and then get the UninstallString value.
Is there nsis expert willing to help me with two code items.
1.) Loop search through subfolders drill down for string match compare on "DisplayName" value starting from "...Windows\CurrentVersions\" or "...Windows\CurrentVersions
\Installer\UserData\"
2.) Then how to get "copy key name" value to extract full path to the folder.
Once this full path is known, then I can ReadRegStr for the UninstallString value within this folder full path to execute the uninstall process.
Thanks,
BD
Instructor
8th April 2005 09:22 UTC
I wanted to write such function, but I confronted with difficulties: root_key cannot pass it value to function without editing function (and other not comfortable ways). I put feature request to change all root_key at runtime.
bd2005
8th April 2005 10:12 UTC
I may have figured it out, shall I email you zip file of the code ? You can simply enter "program name" to search for within "...\Windows\CurrentVersion\Installer\UserData\"
Instructor
8th April 2005 18:20 UTC
I start to write Function "RegSearch". But it'll search in HKLM and HKCU only (using SHCTX - NSIS 2.06).
bd2005
8th April 2005 20:56 UTC
Here's my nsis script to search HKLM Installed\UserData section, works great when used as "standalone".
However, when I copied the Section SEC01 code into Section Uninstall and copied related Functions located above Section Uninstall (not using DetailPrint) ... I get error Call FirstCheck from Section Uninstall.
Any Ideas to workaround this?
Can I look at your "RegSearch"?
How do I create "my function" list?
Thks.
;-----------------------------------------------------
; standalone search program in HKLM Installed\UserData
;-----------------------------------------------------
OutFile "SearchProgram.exe"
ShowInstDetails show
Section SEC01
; Set your 1st ProgramName Here
StrCpy $7 "enter desired program here"
StrCpy $0 0
StrCpy $8 0
Call FirstCheck
DetailPrint $9
DetailPrint $4
; Set your 2nd ProgramName Here
StrCpy $7 "enter desired program here"
StrCpy $0 0
StrCpy $8 0
Call FirstCheck
DetailPrint $9
DetailPrint $4
SectionEnd
Function FirstCheck
EnumRegKey $1 HKLM Software\Microsoft\Windows\CurrentVersion\Installer\UserData $0
IntOp $0 $0 + 1
StrCmp $1 "" done TrySecondCheckAgain
TrySecondCheckAgain:
StrCpy $8 0
Call SecondCheck
done:
FunctionEnd
Function SecondCheck
EnumRegKey $2 HKLM Software\Microsoft\Windows\CurrentVersion\Installer\UserData\$1\Products $8
IntOp $8 $8 + 1
StrCmp $2 "" TryFirstCheckAgain TryThirdCheckAgain
TryThirdCheckAgain:
Call ThirdCheck
TryFirstCheckAgain:
StrCpy $8 0
call FirstCheck
FunctionEnd
Function ThirdCheck
ReadRegStr $3 HKLM "Software\Microsoft\Windows\CurrentVersion\Installer\UserData\$1\Products\$2\InstallProperties" DisplayName
ReadRegStr $5 HKLM "Software\Microsoft\Windows\CurrentVersion\Installer\UserData\$1\Products\$2\InstallProperties" UninstallString
StrCmp $3 $7 ShowDetailInfo
Call SecondCheck
Call FirstCheck
goto SkipDetailPrint
ShowDetailInfo:
;DetailPrint $3
;DetailPrint $5
StrCpy $9 $3
StrCpy $4 $5
SkipDetailPrint:
FunctionEnd
;-----------------------------------------------------
bd2005
9th April 2005 00:54 UTC
Got it.
Add "un." to the function names will allow this set of modules to be executed from "Section Uninstall".
Thks.
Instructor
9th April 2005 14:02 UTC
I complite function if you interesting:
Function "RegSearch" v1.0
bd2005
9th April 2005 15:38 UTC
Wow!
Nice Function!
I'm trying it out now.
When compiling, I get error at this line in example1 section, what am I doing wrong? do I need outfile?
${RegSearch} "HKEY_LOCAL_MACHINE\SOFTWARE\CLASSES" "/F=V /N=Content Type" "Example1"
Instructor
9th April 2005 16:16 UTC
First put function in script and then call it.
Function RegSearch
;...
FunctionEnd
Section
${RegSearch} ...
SectionEnd
bd2005
9th April 2005 18:44 UTC
Ok got it.
Very Nice Script. You know your stuff.
Does this script automatically "drill down" into subfolder path like ... start path - "software\microsoft\currentfolder"
and searches all other subfolder paths within it ?
See my Function in this post, this will search all relavent paths three three layers down from starting path.
Granted it's crappy compaired to yours, I don't know enough nsis to ensure reliability. I would not be surprised if my function fails, but I've got to have reliable means of uninstalling two additional programs if the customer does NOT purchase evaluation primary software.
Instructor
9th April 2005 19:24 UTC
... searches all other subfolder paths within it ?
Yes.
bd2005
9th April 2005 19:37 UTC
Ok ... then perhaps I'm not "seeing" the match found in the Display Screen, using /F=VSK /N=searchvaluename. When I'm using my function with the path and searchvaluename, it shows in my display (but it's probably buggy for distribution with installation software package), seeing how professional your function is, I would like to incorporate your function into my nsis.
I'm looking at R9-R1 values either in DisplayPrint or MessageBox in Section module, shows empty, even though, the "Display Name" key value exists in the Registry matching the "/N=searchvaluename" I'm looking for. Once the match is found, then I can retrieve the "uninstallstring", plug this into uninstall section, proceed onward uninstalling the software. The path is different for each machine as one of the .msi software I'm installing (in addition to my primary software) is always installed in CLSID, thus the actual path is different which makes searching necessary for "display name" in "...\currentversion\...\installedversions\..." etc.
What am I overlooking ?
Thks.
Instructor
10th April 2005 05:23 UTC
Name "Output"
OutFile "Output.exe"
Function RegSearch
;...
Function
Section
${RegSearch} "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" \
"/F=V /N=DisplayName" "RegSearchCallback"
IfErrors 0 +2
MessageBox MB_OK "Error"
SectionEnd
Function RegSearchCallback
ReadRegStr $1 HKLM $R9 'UninstallString'
IfErrors end
SetDetailsPrint both
DetailPrint 'DisplayName:"$R6"'
DetailPrint 'UninstallString:"$1"'
DetailPrint ''
SetDetailsPrint textonly
end:
Push $0
FunctionEnd
bd2005
10th April 2005 06:12 UTC
Thanks so much. I really appreciate your assistance on this. Here's your code I'm running on my machine, looking for "Adobe Acrobat 5.0" to get UninstallString.
I get "Error" popup messagebox from your code, for some reason or another, it doesn't like my registry? If it works on your machine, technically it should work for all machine with the same HKLM path? correct?
;RegSearch by Instructor
Outfile "RegSearch.exe"
Function RegSearch
!define RegSearch `!insertmacro RegSearchCall`
!macro RegSearchCall _PATH _OPTIONS _FUNC
Push $0
Push `${_PATH}`
Push `${_OPTIONS}`
GetFunctionAddress $0 `${_FUNC}`
Push `$0`
Call RegSearch
Pop $0
!macroend
Exch $2
Exch
Exch $1
Exch
Exch 2
Exch $0
Exch 2
Push $3
Push $4
Push $5
Push $6
Push $7
Push $8
Push $R5
Push $R6
Push $R7
Push $R8
Push $R9
ClearErrors
StrCpy $3 ''
StrCpy $4 ''
StrCpy $5 ''
StrCpy $6 ''
StrCpy $7 0
StrCpy $R9 $0 1 -1
StrCmp $R9 '\' 0 +3
StrCpy $0 $0 -1
goto -3
StrCpy $R8 0
StrCpy $R9 $0 1 $R8
StrCmp $R9 '' +4
StrCmp $R9 '\' +3
IntOp $R8 $R8 + 1
goto -4
StrCpy $R9 $0 $R8
IntOp $R8 $R8 + 1
StrCpy $0 $0 '' $R8
StrCmp $R9 'HKLM' +2
StrCmp $R9 'HKEY_LOCAL_MACHINE' 0 +3
SetShellVarContext all
goto ifkeyexists
StrCmp $R9 'HKCU' +2
StrCmp $R9 'HKEY_CURRENT_USER' 0 error
SetShellVarContext current
ifkeyexists:
ReadRegStr $R9 SHCTX $0 ''
IfErrors error
option:
StrCpy $R9 $1 1
StrCpy $1 $1 '' 1
StrCmp $R9 ' ' -2
StrCmp $R9 '' default
StrCmp $R9 '/' 0 -4
StrCpy $R7 -1
IntOp $R7 $R7 + 1
StrCpy $R9 $1 1 $R7
StrCmp $R9 '' +2
StrCmp $R9 '/' 0 -3
StrCpy $R8 $1 $R7
StrCpy $R8 $R8 '' 2
StrCpy $R9 $R8 '' -1
StrCmp $R9 ' ' 0 +3
StrCpy $R8 $R8 -1
goto -3
StrCpy $R9 $1 2
StrCpy $1 $1 '' $R7
StrCmp $R9 'F=' 0 mask
StrCpy $3 $R8
StrCmp $3 '' +6
StrCmp $3 'VSK' +5
StrCmp $3 'VS' +4
StrCmp $3 'V' +3
StrCmp $3 'K' +2
StrCmp $3 'D' 0 error
goto option
mask:
StrCmp $R9 'N=' 0 gotosubdir
StrCpy $4 $R8
goto option
gotosubdir:
StrCmp $R9 'G=' 0 banner
StrCpy $5 $R8
StrCmp $5 '' +3
StrCmp $5 '1' +2
StrCmp $5 '0' 0 error
goto option
banner:
StrCmp $R9 'B=' 0 error
StrCpy $6 $R8
StrCmp $6 '' +3
StrCmp $6 '1' +2
StrCmp $6 '0' 0 error
goto option
default:
StrCmp $3 '' 0 +2
StrCpy $3 'VSK'
StrCmp $5 '' 0 +2
StrCpy $5 '1'
StrCmp $6 '' 0 +2
StrCpy $6 '0'
StrCpy $7 1
Push $0
SetDetailsPrint textonly
popkey:
StrCmp $7 '0' end
IntOp $7 $7 - 1
Pop $R9
StrCpy $R5 ''
StrCpy $R6 ''
StrCpy $R7 ''
StrCpy $R8 ''
StrCmp $6 '0' +3
GetLabelAddress $1 readdefault
goto call
DetailPrint 'Search in: $R9'
readdefault:
StrCmp $3 'V' enumvalue
StrCmp $3 'K' enumkey
ReadRegStr $R6 SHCTX $R9 ''
StrCpy $R5 STR
IfErrors 0 +5
ReadRegDWORD $R6 SHCTX $R9 ''
StrCpy $R5 DWORD
IfErrors 0 +2
StrCpy $R5 BIN
StrCmp $3 'D' 0 +3
GetLabelAddress $1 enumkey
goto +2
GetLabelAddress $1 enumvalue
StrCmp $R6 '' $1
StrCmp $4 '' call
StrCmp $4 $R6 call $1
enumvalue:
StrCpy $0 0
nextvalue:
EnumRegValue $R7 SHCTX $R9 $0
StrCmp $R7 '' enumkey
IntOp $0 $0 + 1
StrCmp $4 '' +3
StrCmp $4 $R7 +2
StrCmp $3 'V' nextvalue
ReadRegStr $R6 SHCTX $R9 $R7
StrCpy $R5 STR
IfErrors 0 +5
ReadRegDWORD $R6 SHCTX $R9 $R7
StrCpy $R5 DWORD
IfErrors 0 +2
StrCpy $R5 BIN
StrCmp $3 'V' +3
StrCmp $4 '' +2
StrCmp $4 $R6 0 nextvalue
GetLabelAddress $1 nextvalue
goto call
enumkey:
StrCmp $5 '0' end
StrCpy $R5 KEY
StrCpy $R6 ''
StrCpy $R7 ''
StrCpy $0 0
nextkey:
EnumRegKey $R8 SHCTX $R9 $0
StrCmp $R8 '' popkey
IntOp $0 $0 + 1
IntOp $7 $7 + 1
StrCmp $R9 '' 0 +3
Push $R8
goto +2
Push '$R9\$R8'
StrCmp $3 'VSK' +2
StrCmp $3 'K' 0 nextkey
StrCmp $4 '' +2
StrCmp $R8 $4 0 nextkey
GetLabelAddress $1 nextkey
goto call
call:
Push $0
Push $1
Push $2
Push $3
Push $4
Push $5
Push $6
Push $7
Push $R5
Push $R9
Call $2
Pop $8
Pop $R9
Pop $R5
Pop $7
Pop $6
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Pop $0
IfErrors error
StrCmp $8 'StopRegSearch' clearstack
StrCpy $R6 ''
StrCpy $R7 ''
StrCpy $R8 ''
goto $1
error:
SetErrors
clearstack:
StrCmp $7 0 end
IntOp $7 $7 - 1
Pop $R9
goto clearstack
end:
SetShellVarContext current
SetDetailsPrint both
Pop $R9
Pop $R8
Pop $R7
Pop $R6
Pop $R5
Pop $8
Pop $7
Pop $6
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Pop $0
FunctionEnd
Section
;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
;HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Installer\UserData
${RegSearch} "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" "/F=V /N=Adobe Acrobat 5.0" "RegSearchCallback"
IfErrors 0 +2
MessageBox MB_OK "Error"
SectionEnd
Function RegSearchCallback
ReadRegStr $1 HKLM $R9 'UninstallString'
IfErrors end
SetDetailsPrint both
DetailPrint 'DisplayName:"$R6"'
DetailPrint 'UninstallString:"$1"'
DetailPrint ''
SetDetailsPrint textonly
end:
Push $0
FunctionEnd
Instructor
10th April 2005 07:40 UTC
hm... I run script in Windows XP and get the same error message.
ReadRegStr $0 HKLM "SOFTWARE\Microsoft" ""
IfErrors 0 +2
MessageBox MB_OK "Error"
In WinMe return no errors (empty or not).
In WinXP return error (only if empty).
Interesting if I manually delete default string "SOFTWARE\Microsoft" in WinXP - no errors.
I'll post bug report about it.
Instructor
10th April 2005 09:52 UTC
You can try changed version "RegSearch" v1.0d