Archive: MUI clobbers regkey when run silently


MUI clobbers regkey when run silently
I have included a script that simply copies files from one directory
to another and registers dlls ocxs. It also creates a shortcut to itself to run in silent mode, but it is named to look like the application it installs.

The idea is that when the user runs the program, they cause the program to automatically update itself from a mapped network drive, then launch - all silently.

The problem is that I have used the Modern UI, and I create the shortcuts based on ${MUI_STARTMENUPAGE_VARIABLE}. When the installer is run silently after the initial install, the regkey that holds the value of ${MUI_STARTMENUPAGE_VARIABLE} gets clobbered so when the uninstall is run the startmenu shortcuts cannot be deleted.

The ${MUI_STARTMENUPAGE_VARIABLE} is read as a blank '' in the uninstaller.

I have included the script here.


Follow up...
After taking a look in the Contrib/Modern UI/system.nsh, I think I have located the problem. The modern UI functions that read the registry key don't get called when the installer is run silenty, but if you are creating shortcuts like this:

; This won't get called in a silent install
; so MUI_STARTMENUPAGE_VARIABLE isn't set.
; This is because it expands to a Page command
; and these are skipped in a silent install.
!insertmacro MUI_PAGECOMMAND_STARTMENU

.
.
.

; The Sections will always run
Section
...
MUI_STARTMENU_WRITE_BEGIN

; This won't do what we expect in a silent install because
; ${MUI_STARTMENUPAGE_VARIABLE wasn't set.
CreateShortCut "$SMPROGRAMS\${MUI_STARTMENUPAGE_VARIABLE}\${MUI_PRODUCT}.lnk" "$INSTDIR\${MUI_PRODUCT}.exe"

MUI_STARTMENU_WRITE_END
...
SectionEnd


The code inside is executed and the code that MUI_STARTMENU_WRITE_END expands to writes the registry key. This means that you will write the shortcuts, AND the registry key will be clobbered if there was one already in the registry.

To make the STARTMENUPAGE stuff work with silent installers as well as for a repair install (one where you already installed but want to install over it), the code to get the default folder should:

1.) Assign the string in the regkey to MUI_STARTMENU_VARIABLE if it exists.
2.) If it doesn't exist, assign the MUI_STARTMENUPAGE_DEFAULTFOLDER to the MUI_STARTMENU_VARIABLE, (which will get written when the MUI_STARTMENU_WRITE_END is reached). And this code should be called before the Page commands are - not in the page command because they won't get called in a silent installer. This requirement makes .onInit a good choice.



To fix the problem, put this line into the .onInit function.

!insertmacro MUI_STARTMENUPAGE_INIT


and the corresponding macro is:

!macro MUI_STARTMENUPAGE_INIT
;Initialize MUI_STARTMENUPAGE_VARIABLE so it is set when we
;are run silently, or as a repair (install over a previous).
Push $R0
ReadRegStr $R0 "${MUI_STARTMENUPAGE_REGISTRY_ROOT}" \
"${MUI_STARTMENUPAGE_REGISTRY_KEY}" \
"${MUI_STARTMENUPAGE_REGISTRY_VALUENAME}"
IfErrors +3
StrCpy ${MUI_STARTMENUPAGE_VARIABLE} $R0
Goto +2

; Get default if no regkey
StrCpy ${MUI_STARTMENUPAGE_VARIABLE} \
"${MUI_STARTMENUPAGE_DEFAULTFOLDER}"
Pop $R0
!macroend


Thank you for reporting this problem :) It has been fixed in the latest CVS version (get it using NSIS Update).