NSIS uninstall and install active at the same time - nsis

I have an NSIS installer that calls an uninstaller to automatically uninstall the older version of the program.
http://nsis.sourceforge.net/Auto-uninstall_old_before_installing_new
Unfortunately, there is the possibility for the user to click on the install, and run the installer before running the uninstall, then proceed with the uninstall...
Is there any way to force the installer in the background while the uninstall is active ?
Edit: tried to disable the "Install" button,
ClearErrors
;disable the Install button
GetDlgItem $R1 $HWNDPARENT 0
EnableWindow $R1 0
...
done:
;disable the Install button
GetDlgItem $R1 $HWNDPARENT 0
EnableWindow $R1 0
I keep disabling the "Close" button on the uninstaller instead. I thought that this section is still in the installer...

I don't see how there can be any UI displayed by .onInit that the user can click on since the main window has not been created yet but if you moved the code somewhere else you could Hide/Show the installer with HideWindow+BringToFront (Basically ShowWindow $HWNDPARENT 0|1) or disable the buttons you don't want the user to click on with GetDlgItem+EnableWindow.

Based on the code snippet you linked to I think that you have no need to worry.
The .onInit function is executed prior to the installer UI being drawn on the screen, hence the uninstaller is going to be run before the user even has a chance to interact with the installer.
Just to make sure you are correctly understanding what that code is doing, when you run the new installer it is looking in the Registry to find the location of the Uninstaller executable of the old version, then popping a message box asking if you would like to uninstall the previous version. If you click ok then it will execute the uninstaller using the ExecWait instruction which will prevent the next instruction from being executed until the uninstaller returns (finishes). If the user clicks cancel it will then skip the uninstall of the old version.
Because all of this is done in the .onInit function, the User has no chance to interact with the new version before the old version is uninstalled.
The only way they could install the new version prior to uninstalling the old version is if they click on cancel when the messagebox comes up. If you would like to remove this option then you could change the MessageBox code too:
MessageBox MB_OK|MB_ICONEXCLAMATION \
"${PROGRAM_NAME} is already installed. $\n$\nClick `OK` to remove the \
previous version"
You also need to remove the IDOK uninst and Abort lines following the MessageBox instruction.
Hope this helps.
The Basic format of your script should be:
Function .onInit
code you linked to goes here
FunctionEnd
Section "Install"
install stuff goes here
SectionEnd
Section "Uninstall"
Uninstall stuff goes here
SectionEnd

call Uninstaller as following.
ExecWait '"$INSTDIR\Uninstall.exe" _?=$INSTDIR'
Then use BringToFront
It will hide Installer until Uninstaller Exists.

Related

How can I create a single NSIS script which will generate different installers based on an input parameter?

I have an application which has development, testing and live versions. I have a command procedure which currently creates 3 different versions of the installer, which can be installed on 3 separate computers.
What I would like to do would be to have one NSIS script which I pass in a parameter to, which will create one of the versions of the installer changing the name of the product and the installation folder. This will allow me to install all 3 versions on the same computer.
What I have tried so far is;
Function .onInit
Var /GLOBAL INSTALL_TYPE
${GetOptions} $CMDLINE "/t" $INSTALL_TYPE
${if} $INSTALL_TYPE == ""
StrCpy $INSTALL_TYPE "Live"
ReadEnvStr $R0 SYSTEMDRIVE
StrCpy $INSTDIR "$LOCALAPPDATA\Programs\MyComp\MyApp$INSTALL_TYPE\"
FunctionEnd
!define MUI_PRODUCT "FCDS-RECAP$INSTALL_TYPE"
OutFile "MyApp-$INSTALL_TYPEinstaller.exe"
One of the main errors I get has to do with MUI_PRODUCT and look similar to;
warning 6000: unknown variable/constant "INSTALL_TYPE.lnk" detected, ignoring (FullDeploymentUser.nsi:121)
warning 6000: unknown variable/constant "INSTALL_TYPE" detected, ignoring (FullDeploymentUser.nsi:124)
Two types of comments would be useful;
This is what you are doing wrong...
This is what you should be doing...
As always any help is appreciated.
MUI_PRODUCT is technically not an official NSIS define, some guy just invented it and used it in a guide.
All instructions starting with ! are preprocessor instructions, those and OutFile and File cannot be controlled by ${GetOptions} because they happen at compile time on your developer machine.
I don't really recommend this 3 in 1 installer solution, it is a bit complicated. It is much better to just create 3 different installers:
!ifndef APPTYPE
!error "APPTYPE not defined"
!endif
Name "MyApp ${APPTYPE}"
OutFile "MyApp ${APPTYPE} setup.exe"
InstallDir "$ProgramFiles\MyApp ${APPTYPE}"
Page Directory
Page InstFiles
Section
SetOutPath $InstDir
File /r "c:\myfiles\MyApp\${APPTYPE}\*"
SectionEnd
and then just generate them with makensis -DAPPTYPE=Beta myapp.nsi etc.
If you really want this 3 in 1 style then you need to use the macros in Sections.nsh to manipulate the sections so that only one of them is visible and active. You also need to mark the install somehow (.ini file?) so that your uninstaller also knows which install type it is uninstalling.

NSIS installs sections even after I have removed them

I have built an installer, which consists of 5 sections/components. I have created a pre-function before the components page to check which components are installed, only the components that are not currently installed should be shown on the components page.
!define MUI_PAGE_CUSTOMFUNCTION_PRE selectSections
!insertmacro MUI_PAGE_COMPONENTS
...
Function selectSections
; remove sections which are already installed
ReadRegStr $0 HKLM "${REG_INSTALL}" "SEC_EXTRACTOR"
IfErrors +2
!insertmacro RemoveSection ${SEC_EXTRACTOR}
!insertmacro SelectSection ${SEC_EXTRACTOR}
; so on for all components
FunctionEnd
So I install all the components first, and then run the installer again. This time I do not see any components on the components page. But when I press install on that page, all the sections are still executed. Can anyone help ?
(I have pressed the install button from a components page, that does not list any components. but I see those sections being installed in the details pane.)
Don't use relative jumps to skip macros because a macro can be more that one instruction. Use IfErrors label or ${If} ${Errors} from LogicLib.nsh.

NSIS uninstaller - App Name missing (set dynamically)

I created an NSIS installer where the name of the app is taken from an .INI file (it has to be so since it will be used for multiple apps).
Name $APP_NAME
....
Function .onInit
ReadINIStr $R3 ${TECHPUB_INI_FILE} "General" "Installer_name"
StrCpy $APP_NAME $R3
....
FunctionEnd
....
Section install
....
WriteUninstaller $INSTDIR\Uninstall.exe
....
SectionEnd
The app name is correctly shown on the installer and it's the one from the .INI file. When I uninstall the app, the name is missing.
http://i48.tinypic.com/1934w9.png
Everything else works (uninstall removes all it has to remove). Any idea how to fix this?
Thank you!
The init function of the uninstaller is a separate un.onInit function. See Uninstall Callbacks.

How to uninstall previous version silently using NSIS script?

I need to uninstall previous version if installed already. I have a NSIS script. Here is what I have tried:-
Function UninstallPreviousVersion
ReadRegStr $R0 ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName"
StrCmp $R0 "" done remove
remove:
DetailPrint "Removing previous installation."
ExecWait '"$INSTDIR\uninst.exe" /S _?=$INSTDIR'
done:
FunctionEnd
But When I run it instead of uninstalling old and install new version. it creates a new folder 'bin' under installation folder.
Any help please?
You might want to read the uninstall directory from the registry in case the old install location is not the same as $instdir but this is not your real problem. Your code does look correct so I suggest you do some "MessageBox debugging" in your uninstaller code...

NSIS Overwrites Shortcuts

Is there any way to tell NSIS not to overwrite my start menu shortcut. The reason I don't want it to overwrite is so the user's command line options aren't cleared when they upgrade to a new version. I've tried this to no avail:
Section -AdditionalIcons
SetOverwrite off
CreateDirectory "${START_MENU_DIR}"
CreateShortCut "${START_MENU_LNK}" "$INSTDIR\${PRODUCT_NAME}.exe"
SectionEnd
Why can't you just check with IfFileExists ?
If you wanted to go all out, you could update the path and working dir, but leave the parameters and icon in place, but to do that you would have to call the IShellLink COM interface on your own (With the system plugin or a custom plugin/app)
Here is an example that works:
Section -AdditionalIcons
CreateDirectory "${START_MENU_DIR}"
IfFileExists "${START_MENU_LNK}" SkipShortcut
CreateShortCut "${START_MENU_LNK}" "$INSTDIR\${PRODUCT_NAME}.exe"
SkipShortcut:
SectionEnd

Resources