- NSIS Discussion
- Syntax question
Archive: Syntax question
patelb
14th July 2008 22:23 UTC
Syntax question
I have this in my uninstall section:
Section "Uninstall"
!include "$instdir\unifilelist.nsh"
SectionEnd
I keep getting this error though:
!include: could not find: "$instdir\unifilelist.nsh"
The file is in the $instdir, if I remove $instdir and put in a hardcoded value everything works.
For example this works:
Section "Uninstall"
!include "c:\somefolder\unifilelist.nsh"
SectionEnd
How do I include variables in that !include directive?
LoRd_MuldeR
14th July 2008 22:51 UTC
"!include" is a preprocessor command, evaluated at compile time. But $INSTDIR is a variable, which will have a value only at runtime, when the installer is executed. You shouldn't mix that up! Define a symbol instead! Try like this:
!define uninstfile "c:\somefolder\unifilelist.nsh"
...
Section "Uninstall"
!include "${uninstfile}"
SectionEnd
patelb
14th July 2008 23:02 UTC
But the file will be inside the install directory, and since the install directory will be different with each install is there a way to make this whole process dynamic?
I cant do this either because it still gives me the same error:
!define unfiles "$instdir\unifilelist.nsh"
LoRd_MuldeR
14th July 2008 23:14 UTC
You can't include a .nsh file from the user's install directory! That's because the "!include" instruction is a preprocessor command that will be evaluated at the moment when you *compile* the installer! It will *not* be evaluated when the user runs the installer/uninstaller, like normal installer instructions. Therefore the "!include" command requires a path to some file on your local machine, which needs to be present at the moment when you *compile* your installer. Hope that is clear now!
BTW: The same applies to all preprocessor commands. Those can be easily identified, because they start with a "!" character ;)
patelb
14th July 2008 23:18 UTC
Ok that makes sense. What is norm in this situation then? If people use a list of files to build the uninstall section, do they just hard code where that file will reside?
LoRd_MuldeR
14th July 2008 23:24 UTC
Originally posted by patelb
Ok that makes sense. What is norm in this situation then? If people use a list of files to build the uninstall section, do they just hard code where that file will reside?
Either that, or you load the file names from a plain text file at *runtime* like this:
Section "Uninstall"
ClearErrors
FileOpen $0 "$INSTDIR\files.lst" r
IfErrors done
Loop:
FileRead $0 $1
IfErrors LoopEnd
Delete "$1"
Goto Loop
LoopEnd:
FileClose $0
done:
SectionEnd
The "files.lst" would need to look like:
C:\Program Files\Foobar Deluxe\File1.foo
C:\Program Files\Foobar Deluxe\File2.foo
C:\Program Files\Foobar Deluxe\File3.foo
...
The "files.lst" must be generated during install...
patelb
14th July 2008 23:29 UTC
Very clever!
LoRd_MuldeR
14th July 2008 23:51 UTC
Nevertheless, in most cases you will be fine with:
Section "Uninstall"
RMDir /r /REBOOTOK "$INSTDIR"
SectionEnd
The variable $INSTDIR will contain the install directory selected by the user at *runtime* and it is available in both, the installer and uninstaller. The uninstaller code above will simply remove the entire Install folder including all files and subdirectories. Also all files added *after* install would be erased...
For an advanced solution have a look at:
http://nsis.sourceforge.net/Advanced...og_NSIS_Header
patelb
14th July 2008 23:58 UTC
I thought this was unsafe:
_http://forums.winamp.com/showthread.php?s=&threadid=289986
LoRd_MuldeR
15th July 2008 00:06 UTC
Well, I'd say it's safe. In the uninstaller $INSTDIR will contain the path where the "Uninstall.exe" is located. That should be the Install folder of your application, otherwise your Uninstall.exe is mislocated! So as long as you don't expect the user to store any important files within your Install folder, it should be save to erase the $INSTDIR folder at uninstall. More subtle solutions can be implement using $INSTDIR, like "Delete $INSTDIR\Bin\*.exe", instead of deleting the entire $INSTDIR folder. And if you want an advanced solution, see the link from my previous post...
BTW: Are Hyperlinks in my posts visible to other users? :confused:
patelb
15th July 2008 00:30 UTC
I can see them
LoRd_MuldeR
15th July 2008 00:39 UTC
Good :)
Also keep in mind that when you store *full* paths during install, the Uninstaller would fail horrible if the user renamed or moved the installer folder! Therefore I would use $INSTDIR in my uninstaller to avoid such problem. Even if you want to store all files in a text file and read that text file during uninstall, I would *not* use full paths (as shown in my example above). I would store paths *relative* to the $INSTDIR folder, so when the user moves or renames the Install folder, your uninstaller still works...
Section "Uninstall"
ClearErrors
FileOpen $0 "$INSTDIR\files.lst" r
IfErrors done
Loop:
FileRead $0 $1
IfErrors LoopEnd
Delete "$INSTDIR\$1" ; <- SEE HERE
Goto Loop
LoopEnd:
FileClose $0
done:
SectionEnd
File1.foo
File2.foo
Data\File3.foo
Data\File4.foo
Data\Stuff\File5.foo
...
patelb
15th July 2008 00:41 UTC
That "looping" solution you gave me earlier, on the fileread command its reading the line break also. So the delete command is not working properly. Is there like a chomp function in nsis that will fix this?
LoRd_MuldeR
15th July 2008 00:44 UTC
See "NSIS\Docs\StrFunc\StrFunc.txt" for info ;)
Look out for ${StrTrimNewLines} :D
Fixed code should look like:
!include "StrFunc.nsh"
${StrTrimNewLines}
Section "Uninstall"
ClearErrors
FileOpen $0 "$INSTDIR\files.lst" r
IfErrors done
Loop:
FileRead $0 $1
IfErrors LoopEnd
${StrTrimNewLines} $2 "$1" ; <- Remove carriage returns
Delete "$INSTDIR\$2"
Goto Loop
LoopEnd:
FileClose $0
done:
SectionEnd
files.lst:
File1.foo
File2.foo
Data\File3.foo
Data\File4.foo
Data\Stuff\File5.foo
...