Hi all,
In some situations I want the following to happen when running the setup: uninstall first the version that is aleady installed and then install the new version. For this I do:
a) - run first the UninstallString
b) - then check if there were errors, by using IfErrors, as I don't want to start the installation if in the uninstaller was a problem
c) - if there were no errors, install
Now, I'm having some issues with the step b. Issues:
1) I have some files in use, so I know that the delete call from the uninstaller will not work right away only over the reboot, but as the help states, the error flag will anyhow be set so it will be considered that the uninstaller failed, even though everything worked as expected. What should I do in this case? How can I specify that not being able to delete a file is not an error and shouldn't set the error? In other words how can I make a difference between a real error (like cancel was pressed) and an expected behaviour" (like file will be deleted only over reboot)?
2) During uninstalling I call in some cases the Quit command. When the program goes on one of these ways, I know for sure that the uninstaller failed. So, in these cases how could I set the error? I mean would be ok to just call SetErrors just before the Quit?
Thx,
Viv
IfErrors after running the uninstaller
9 posts
1) I have some files in use, so I know that the delete call from the uninstaller will not work right away only over the reboot, but as the help states, the error flag will anyhow be set so it will be considered that the uninstaller failed, even though everything worked as expected. What should I do in this case? How can I specify that not being able to delete a file is not an error and shouldn't set the error? In other words how can I make a difference between a real error (like cancel was pressed) and an expected behavior" (like file will be deleted only over reboot)?To me, this seems like ideal behavior. Because, until you've rebooted to delete the in-use files, the old app really isn't uninstalled. Installing the new app over the top of the old one in this state could lead to unexpected results. For this reason, it might be good to force the user to reboot.
But, if you like, you can use SetErrorLevel to set the error level to whatever you want. (you may even want to set to a custom error level to allow your main script track the error as being becuase of a reboot flag vs. a problem with the actual uninstall.)
For your second question, it would be best to use ABORT instead of QUIT. (see help manuals on special uses for abort.) If that's not an option, then perhaps create your own quit macro this:
Then, define ${QuitEx} like this:
!macro QuitEx
SetErrorLevel 2
Quit
!macroend
You can then substitute ${QuitEx} anywhere you would normally call QUIT by itself.
!define QuitEx "!insertmacro QuitEx"
Hi Comperio,
Thx for your answer.
For 2):
I can't use Abort, as I sometime need to abort the installer from a custom page, and abort in those cases has another meaning. So I use quit instead.
I will implement your idea with QuitEx which will do what I need. I actually thought that the Quit call will set itself the error to smth different than 0.
For 1):
I could use indeed the SetErrorLevel but I'm not sure how. Let's assume somewhere on the way the uninstaller has an error and sets the error itself to some value, eg 2. Later I try to do the deletion of the files which will fail, but as I don't want the uninstaller to report failure just b/c a file couldn't be deleted, I will SetErrorLevel to 0 or smth else, so I will actually loose the error 2 from above, which is not ok right? Or is my logic somehow wrong?
Thx,
Viv
Thx for your answer.
For 2):
I can't use Abort, as I sometime need to abort the installer from a custom page, and abort in those cases has another meaning. So I use quit instead.
I will implement your idea with QuitEx which will do what I need. I actually thought that the Quit call will set itself the error to smth different than 0.
For 1):
To me, this seems like ideal behavior. Because, until you've rebooted to delete the in-use files, the old app really isn't uninstalled. Installing the new app over the top of the old one in this state could lead to unexpected results. For this reason, it might be good to force the user to reboot.Yes, I agree, but for me this is not an option. Problem is that I have a dll that is always in use by several applications on the machine, which would mean that I would need a reboot after uninstalling, and then again a reboot after installing, so that all app will load this dll. Unfortunatelly this (2 reboots) is smth that the users will hate, so I try to do both in one step and reboot only once afterwards. So, I take care in my installer and work under the assumption that some files might have not been removed by the uninstaller and won't be until a reboot.
I could use indeed the SetErrorLevel but I'm not sure how. Let's assume somewhere on the way the uninstaller has an error and sets the error itself to some value, eg 2. Later I try to do the deletion of the files which will fail, but as I don't want the uninstaller to report failure just b/c a file couldn't be deleted, I will SetErrorLevel to 0 or smth else, so I will actually loose the error 2 from above, which is not ok right? Or is my logic somehow wrong?
Thx,
Viv
I would probably add something like this to end of the uninstall section:
This way, if any errors are detected, it will exit with errors. Otherwise, if there are no errors, it will return zero even if the reboot flag was set. (Note: I'm not sure if the last SetErrorLevel call is needed if the reboot flag is reset, but I added it here just in case.)
...
IfErrors +3 0
SetRebootFlag false
SetErrorLevel 0
SectionEnd
I thought that actually if you do a delete over reboot for a file in use the error will be set and if this is true the
I mean, I think, a delete over reboot will set the error too, not only the reboot flag. or no?
Thx,
Viv
will always be true so the
IfErrors +3 0
will never be executed.
SetRebootFlag false
SetErrorLevel 0
I mean, I think, a delete over reboot will set the error too, not only the reboot flag. or no?
Thx,
Viv
btw, I did some tests, see:
b/c of this I decided to do like:
- the QuitEx you suggested (so before a quit I always set the error)
- if the uninstaller gets to the very last line of code from the script, I set there the error to 0, as I assume nothing went wrong and the uninstaller did it's whole job
I think this is the safest way, as in this way I have errors when I specifically QUIT the unistaller, or if smth on the way went wrong and stopped the uninstaller, but I'll have success once the uninstaller gets to the last line of code, regardless if the deleted files were in use or not.
Viv
Are you a developer who uses NSIS to distribute your application? Are you a Winamp plug-in developer who wants to use NSIS to distribute your plug-in? Have suggestions for other people like you? This is the place.
b/c of this I decided to do like:
- the QuitEx you suggested (so before a quit I always set the error)
- if the uninstaller gets to the very last line of code from the script, I set there the error to 0, as I assume nothing went wrong and the uninstaller did it's whole job
I think this is the safest way, as in this way I have errors when I specifically QUIT the unistaller, or if smth on the way went wrong and stopped the uninstaller, but I'll have success once the uninstaller gets to the last line of code, regardless if the deleted files were in use or not.
Viv
OK, going back to the original post, I feel there have been some asumptions made that are false. I'd like to address them here just to avoid confusion to anyone who might read this post:
Here's my test I did to confirm:[list=1][*]I created a dummy exe (Let's refer to it as "EXE1")[*]Next, I created an uninstaller ("EXE2") with a command "Delete /rebootok exe1.exe". I follow this by an iferrors statement to check for errors. (A message box displays if there are errors).[*]Then, I created a 3rd exe (which I'll call "EXE3") that calls the EXE2 using ExecWait and the ?_ switch (to prevent copying of the uninstall to temp) and then captured the exit code in $R0.[*]Now, with the first exe running, I executed EXE3.[/list=1]
What I found was that there were NO errors in the delete command when using the /rebootok flag, but there WERE errors if I omitted /rebootok.
I also found that the regardless of errors, the uninstall exit code was always 0.
So, this now tells me that my original IfErrors suggestion should have worked. It also tells me that the assumption that the the uninstall returns an error if the files cannot be deleted is false.
I've attached my sample files in case anyone is curious.
Here's my test I did to confirm:[list=1][*]I created a dummy exe (Let's refer to it as "EXE1")[*]Next, I created an uninstaller ("EXE2") with a command "Delete /rebootok exe1.exe". I follow this by an iferrors statement to check for errors. (A message box displays if there are errors).[*]Then, I created a 3rd exe (which I'll call "EXE3") that calls the EXE2 using ExecWait and the ?_ switch (to prevent copying of the uninstall to temp) and then captured the exit code in $R0.[*]Now, with the first exe running, I executed EXE3.[/list=1]
What I found was that there were NO errors in the delete command when using the /rebootok flag, but there WERE errors if I omitted /rebootok.
I also found that the regardless of errors, the uninstall exit code was always 0.
So, this now tells me that my original IfErrors suggestion should have worked. It also tells me that the assumption that the the uninstall returns an error if the files cannot be deleted is false.
I've attached my sample files in case anyone is curious.
I wonder what kichik can tell us about this. It might well be a bug perhaps.
-Stu
-Stu
The error flag is not set if the file is set to be deleted on reboot. The reboot flag is set instead.
As for the return values of the installer itself, see appendix D.
As for the return values of the installer itself, see appendix D.