0
votes

Using NSIS, I want to call the uninstaller of a previously installed version from my installer before installing the new version. The proposed solution for this is to execute the following command:

ExecWait '"$INSTDIR\uninstall.exe" _?=$INSTDIR'

As far as I understood, the _?=$INSTDIR is needed to make the ExecWait truly waiting. Without it, NSIS would copy the uninstaller to the temp directory, start it there, and then return before the uninstaller finishes. The problem with this solution is, that the uninstaller is directly executed in the $INSTDIR. This leads to the effect that the following command in my uninstaller fails:

Delete "$INSTDIR\uninstall.exe"

As far as I understood, the reason why uninstall.exe is not deleted is, that a file which is currently being executed cannot be deleted. To summarize my problem:

ExecWait '"$INSTDIR\uninstall.exe"'

doesn't wait for the uninstaller to finish and

ExecWait '"$INSTDIR\uninstall.exe" _?=$INSTDIR'

doesn't allow the uninstaller to delete itself. Does anybody know, how to wait for an uninstaller to finish while at the same time allowing the uninstaller to instantly delete itself within the uninstallation process?

1
ExecWait ALWAYS waits for the child process, in your case this child process just finishes fast... - Anders
I read that ExecWait only waits until the uninstaller is copied to and started in the temp directory. It definitively doesn't wait for the uninstaller to finsih. I tested this using some message boxes. - honk
ExecWait is a generic instruction and it ALWAYS waits for the child process, the fact that the thing you executed (the uninstaller) will exit quickly is not ExecWaits fault. ExecWait is a thin wrapper around the native CreateProcess & WaitForSingleObject functions... - Anders
I think we have the same understanding. My idea was not to blame ExecWait here. I wanted to mention, that the given solution which uses ExecWait doesn't do what I expected it to do. - honk

1 Answers

4
votes

The _?= parameter tells the uninstaller that it should not copy itself to %temp% and execute that copy without waiting for it to complete. The path after _?= is used to initialize $InstDir in the uninstaller.

In your installer you can do something like this:

InitPluginsDir
;ReadRegStr $oldinstall ... ; Somehow detect old install
CreateDirectory "$pluginsdir\unold" ; Make sure plugins do not conflict with a old uninstaller 
CopyFiles /SILENT /FILESONLY "$oldinstall\uninst.exe" "$pluginsdir\unold"
ExecWait '"$pluginsdir\unold\uninst.exe" _?=$oldinstall'