Archive: EnumRegValue search question on unknown subfolders


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


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.


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\"


I start to write Function "RegSearch". But it'll search in HKLM and HKCU only (using SHCTX - NSIS 2.06).


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


Got it.
Add "un." to the function names will allow this set of modules to be executed from "Section Uninstall".

Thks.


I complite function if you interesting:

Function "RegSearch" v1.0


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"


First put function in script and then call it.

Function RegSearch
;...
FunctionEnd

Section
${RegSearch} ...
SectionEnd

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.


... searches all other subfolder paths within it ?
Yes.

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.


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

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


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.

You can try changed version "RegSearch" v1.0d