Archive: (Yet another) Uninstall before Install question.


(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?

I'm thinking it has something more to do with a space being there. Try ExecWait '$R1 "_?=$INSTDIR"'


I tried it but nothing happened. ExecWait does not wait even if $INSTDIR include "Program Files". But I'll try else.


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


I modified basic.nsi from Examples-dir (see attachment). What's wrong? I don't understand.


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


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


Using of

ExecWait '"$R1" _?=$INSTDIR'
solved this problem for me.

ADD

makensis.nsi must be edited.:)

makensis.nsi reads a string that is already quoted.


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.

ExecWait may fail if the command isn't properly quoted. But it is properly quoted in makensis.nsi as $R1 contains the quotes.


I think if ExecWait failed than error flag must be set. In my example ExecWait exit without error flag seting.
Is this normal?


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.


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.


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:


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

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?


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.

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!


Got me confused too so I'll just write down all the facts.