- NSIS Discussion
- (Yet another) Uninstall before Install question.
Archive: (Yet another) Uninstall before Install question.
Arrby
6th April 2005 23:45 UTC
(Yet another) Uninstall before Install question.
NSIS Version 2.05:
I have my installer doing the check for existing installation and doing uninstall first, essentially just as NSIS itself does (I stole the custom screen and functions right from makensis.nsi in the Examples folder).
I have discovered the following problem (bug?).
The code:
HideWindow
ClearErrors
ExecWait '$R1 _?=$INSTDIR'
...
...
BringToFront
does what one expects / wants
If and Only If the folder
"Program Files" is included
somewhere in the value of $INSTDIR, at the time the function is being executed. If $INSTDIR does
NOT include
"Program Files" in its value, the ExecWait
Does Not Wait!.
Note, it doesn't seem to matter what drive the installation was to, and $INSTDIR is the
correct value of the "previous" installation, so the uninstall works correctly, it just doesn't wait, i.e the installer continues to run as if the ExecWait had been an Exec.
Is there something I can add to the code to force it to wait when the "previous" installation was NOT to a folder underneath a "Program Files" folder?
Afrow UK
7th April 2005 11:57 UTC
I'm thinking it has something more to do with a space being there. Try ExecWait '$R1 "_?=$INSTDIR"'
glory_man
7th April 2005 12:05 UTC
I tried it but nothing happened. ExecWait does not wait even if $INSTDIR include "Program Files". But I'll try else.
Afrow UK
7th April 2005 12:14 UTC
Here's your problem...
ExecWait '$R1 _?=$INSTDIR'
Need quotes around $R1 incase it contains spaces.
ExecWait '"$R1" "_?=$INSTDIR"'
Edit: If you've got Program Files in there, e.g.
C:\Program Files\myApp\file.exe
it will treat "C:\Program" as the program to execute, and "Files\myApp\file.exe" as a paramater.
-Stu
glory_man
7th April 2005 13:13 UTC
I modified basic.nsi from Examples-dir (see attachment). What's wrong? I don't understand.
Afrow UK
7th April 2005 16:05 UTC
Hmm you're right it doesn't wait whatever path it is. It doesn't even wait if I do not use the _?= param.
I think the only solution at the moment, is to wait until some specific file is gone (so you know it's been uninstalled) before continuing with install...
ExecWait '"$R1" "_?=$INSTDIR"'
Sleep 1000
IfFileExists "$INSTDIR\some_file.ext" -1
Edit: Though if user cancels uninstall it will loop forever :cry:
-Stu
Afrow UK
7th April 2005 16:08 UTC
Ok, then you should get the Uninstall to create a temp file in un.onInit and delete it in un.onUninstSuccess, un.onUninstFailed, un.onUserAbort, and lastly un.onGUIEnd (if user does Ctrl+Alt+Del in some cases!)
-Stu
glory_man
7th April 2005 17:37 UTC
Using of
ExecWait '"$R1" _?=$INSTDIR'
solved this problem for me.
ADD
makensis.nsi must be edited.:)
kichik
7th April 2005 17:45 UTC
makensis.nsi reads a string that is already quoted.
glory_man
7th April 2005 18:05 UTC
I understand that ExecWait don't wait if command without spaces and not in quotes.
From documentation:
Note, if the command could have spaces, you should put it in quotes to delimit it from parameters.
...
If you don't put it in quotes it will not work on Windows 9x with or without parameters.
I use WinXP.
kichik
7th April 2005 18:09 UTC
ExecWait may fail if the command isn't properly quoted. But it is properly quoted in makensis.nsi as $R1 contains the quotes.
glory_man
7th April 2005 18:18 UTC
I think if ExecWait failed than error flag must be set. In my example ExecWait exit without error flag seting.
Is this normal?
kichik
7th April 2005 18:22 UTC
The error flag is set if CreateProcess fails. If the process was not created and the error flag was not set, it's not normal. I'd guess the process was created but exited before you noticed. Which exact example are you referring to? You said the last one worked.
glory_man
8th April 2005 14:08 UTC
2 kichik
Yes, if i use ExecWait '"$R1" _?=$INSTDIR' all works.
I just try to say that command must be in quotes not only for Win98 or if the command has spaces. But even if WinXP and command has not spaces.
Arrby
8th April 2005 21:46 UTC
Thanks everyone. THANK YOU glory_man!:up:
Putting the "" around $R1 did the trick.
I must admit to being completely mystified as to why, though.
Why does the uninst program (spawn nowait?)itself if $R1 in unquoted AND the $INSTDIR path does NOT contain any spaces, but either doesn't spawn itself or spawns itself WITH wait when $R1 is unquoted AND the $INSTDIR DOES contain at least one folder WITH spaces?
Why does quoting R1, i.e. "$R1" cause the uninstall program
to either not spawn itself or spawn WITH wait regardless of whether $INSTDIR contains a folder with spaces or not?
Or why does it at least SEEM to work this way?:confused:
Afrow UK
8th April 2005 23:13 UTC
Why you need quotes around the path:
If you've got 'Program Files' in there, e.g.
C:\Program Files\myApp\file.exe
it will treat "C:\Program" as the program to execute, and "Files\myApp\file.exe" as a paramater (when it should be the whole lot).
With the _?= switch, everything after it is passed into the $INSTDIR var. So, say if I were to do _?=C:\ /silent (what one might think are two seperate paramaters) would set $INSTDIR to "C:\ /silent"
I'm not sure though why that should stop ExecWait from waiting. Perhaps the uninstaller trips on that error with the quotes around _?= and the value and ExecWait thinks it's aborted.
I'm guessing if you use "_?=C:\" then $INSTDIR will be C:\" which is a bad path already (can't have double quotes in paths)!
-Stu
Arrby
9th April 2005 19:47 UTC
Curiouser and Curiouser:
Take glory_man's test script.
Test with all 4 of the following variations:
1: ExecWait '$R1 _?=$INSTDIR' ;taken from makensis.nsi
2: ExecWait '$R1 "_?=$INSTDIR"'
3: ExecWait '"$R1" "_?=$INSTDIR"'
4: ExecWait '"$R1" _?=$INSTDIR'
For your tests do the following:
Initial install: choose a path with at least one
folder in it that has embedded spaces, i.e I chose:
E:\P F\ExecTest
After the install, immediately run the installer again. Pay attention to the task bar as your running.
After the UNINSTALL takes place, when you get to the directory page, modify the path to remove the spaces from ALL folders in the path. I.e. I changed it to:
E:\PF\ExecTest
Run the installer a third time, watch the task bar as you
go thru the UNinstaller routine.
Obviously options 3 or 4 are the options to use for desired behaviour. I am real curious as to WHY we would EVER want the uninstaller to behave as it does for options 1 and 2.
Why is the uninstaller EVER spawning itself with a NOWAIT,
and should it?
kichik
9th April 2005 20:55 UTC
Assuming $R1 doesn't already contain the quotes, the right method is:
ExecWait '"$R1" _?=$INSTDIR'
The others are wrong.
The uninstaller spawns a copy of itself so it'll be able to delete itself.
Arrby
9th April 2005 21:58 UTC
The last form you showed is the same one I chose, Thanks!
One last word and I'll let this topic die.
Based on the behaviour with Unquoted $R1 (when R1 itself is NOT a quoted string) when the paths do and dont contain embedded blanks (my last post makes the behaviour clear). Are you sure the current behaviour is NOT the OPPOSITE of what it should be? I.E. why does it WAIT when the unquoted $R1 var contains a non-quoted string with embedded blanks, but FAIL to WAIT when the unquoted $R1 var contains a non-quoted string WITHOUT embedded blanks. I am probably just completely confused, but it seems the second case should be the case in which the unistaller sees it is being executed from the SAME directory it is deleting (no embedded blanks in the path), and it should be the first case (embedded blanks) when it thinks its being run from a SEPERATE directory from the one it is deleting. Why does it need to spawn itself with NO_WAIT when it is running from a DIFFERENT path than it is deleting, but DOESNT need to spawn itself (or at least spawns itself with WAIT) when it is running from the SAME directory it is deleting.
This is what has me so confused!
kichik
9th April 2005 22:08 UTC
Got me confused too so I'll just write down all the facts.
- Using Exec, ExecWait or ExecShell with an unquoted path is never a good idea. It doesn't have to do with waiting or not waiting, just the success of running the process itself. Windows might simply fail creating the process or it might execute a different executable.
- When you execute an uninstaller without _?=, it copies itself to the temporary directory, runs the copy with _?=$EXEDIR and quits immediately.
- When you pass an uninstaller _?=path, it sets $INSTDIR and $OUTDIR to path and starts doing its job.