How to put functions in different files in NSIS - nsis

I have a couple of functions in the NSIS installer. I want to keep them neatly in separate files.
For example, the main section is in the files installer.nsi and now I want to put a function to compare versions in a separate file. How can I do that?

You can make your own include files (just a normal text file with the .nsh extension):
VersionCompare.nsh:
Function MyVersionCompare
# ...
FunctionEnd
Installer.nsi:
Name "MyInstaller"
OutFile "MyInstaller.exe"
!include "VersionCompare.nsh"
Section
Call MyVersionCompare
SectionEnd

Related

Count Files Inside NSIS

I have a NSIS executable files and I just want to list the numbers of files inside each of the files.
Is there any way on how to determine the count of files inside the setup.exe or NSIS files without extracting it?
NSIS itself does not support this.
7-zip is able to understand most NSIS installers and you can use their command line tool to get a file listing.

How to read the contents of a packed file when the uses cancels an NSIS installation?

I want to report to a Web Service whether the installation completed successfully or not. The identifiers that need to be passed to the service are stored in an uncompressed text file along with the other (compressed) files. Everything works on a successful installation, but when the user cancels the installation, no files are extracted (as expected) and I am unable to find a way to extract a specific file from the archive.
I have considered some other options (writing a custom plugin, parsing through the installer executable file), but I hope there is a cleaner solution.
You can extract files at any point in the installer, in your case probably in .onInstFailed or .onUserAbort:
Function .onInstFailed
InitPluginsDir
SetOutPath $pluginsdir
File something.ext
; Do something with "$pluginsdir\something.ext"
; Note: $pluginsdir is automatically deleted when installer quits...
FunctionEnd

Compiling and executing an nsi file from another nsi file using nsis code

Suppose I have two nsi files demo.nsi (compiles to demo.exe) and setup.nsi. (compiles to setup.exe). I want to use demo.nsi inside setup.nsi in such a way that when setup.exe is executed, it compiles the demo.nsi, and then executes the demo.exe.
Just want to know if that is possible to do in nsis ?
Thanks.
Sure, it could be possible like from e.g. any batch file:
you need to call ExecWait to call makensis.exe for the compilation part
and you can call the final executable with either ExecWait or Exec depending on you need to wait for the result or not.
Beware that if you want to do that in any host, and not only the one where you prepare your setup, you will have to embed the NSIS distribution in your setup to be able to call makensis.exe and all the included files that could be necessary (included files, plugins, and other resources).

How do I replace strings in files with output from a script in NSIS?

I have an installer working with NSIS that I'm updating at the moment. At several points, the installer needs to configure packages by replacing paths or values inside configuration files. Those configuration files have placeholders in them that are replaced by whichever deployment tool I'm using (NSIS for this specific case).
Scripts are mostly PHP scripts written to do some simple tasks that would have been excruciatingly complex in NSIS. For some reason though I keep going back to making my PHP scripts replace the placeholders by themselves instead of doing it in the NSIS script, which just isn't right.
My code looks like:
nsExec::ExecToStack '"$INSTDIR\Php\php.exe" "$INSTDIR\Apache\tools\findport.php"'
pop $1 ; return code
pop $2 ; port number
!insertmacro _ReplaceInFile "Apache\conf\httpd.conf" "APACHE_PORT" "$2"
The _ReplaceInFile macro comes from http://nsis.sourceforge.net/ReplaceInFile and works just fine if I use $INSTDIR instead of $2 in the above example. Showing $2 in a MessageBox shows the port number just fine.
I guess I'm doing something wrong but I can't figure out what it is, and debugging is a pain with NSIS.
Thanks,
I guess the lesson is to always verify paths before blaming the utility functions (Using Process Monitor is a good idea so you can tell if file-system redirection is getting in the way)
I would also like to add that using $instdir to hold anything other than a path is not a good idea since it will strip away invalid path characters behind your back. Use a normal register or a custom variable...

NSIS - Delete all files except one file

Could any one clarify me that, when uninstalling I need to delete everything form the Installation folder except the License file. How can I do it with NSIS scripting?
Thanks
Regards,
RoboAlex.
Instead of opening the file, as in Anders' third point, I'd do it this way:
Rename $INSTDIR\license.txt $PLUGINSDIR\license.txt
RMDir /R $INSTDIR # Remembering, of course, that you should do this with care
CreateDirectory $INSTDIR
Rename $PLUGINSDIR\license.txt $INSTDIR\license.txt
Depending on when it gets to the file it can't delete, RMDir /R may leave most of it behind, as I believe it will stop when it can't delete something; this way will get rid of it all properly. This will also lose the directory stats, but that's probably not important.
I'd recommend one of Anders' first two solutions over this, though. They're more precise.
Off the top of my head, there are 3 ways to do this:
Use Delete on one file at the time on a list generated at compile time with !system etc
Use FindFirst/FindNext/FindClose at runtime and Delete everything except the license based on filename
A bit of a hack, but you should be able to open the license file for write/append, then Delete/RMDir will not be able to delete the file since it has a open handle.

Resources