Archive: Reuse same logic on several files to choose which files to install.


Reuse same logic on several files to choose which files to install.
Hello. I'm new to NSIS, but have been searching Wiki, FAQ, manual, forum, and Google for hours and can't make progress. If you can point me in the right direction, thanks.

I have a handful of files. I want them all stuck into the installer, in case they are needed. For each file, I want the installer to check if the destination exists. If it exists, then I want to make a backup by renaming with a .bak extension. If the backup exists, I don't want to touch the backup. I do not want to clobber any files. If there is a backup, and no original (for whatever odd reason), then I'll just install the file, but not touch the .bak.

I have worked out the logic to achieve this. I was trying to stick this logic into a Function or a Macro, so that I could reuse it. This would mean passing the file name as a parameter. I keep getting an error from the File command, because it apparently does not like variables. I have fiddled with the /oname switch, but File still requires a static name at the end.

Wiki Examples 3.2.1 and 3.2.2 clearly show File being passed as a variable inside both a Macro and a Function, which is the first relevant document I read. It appears these examples are incorrect. Or else it fails to demonstrate how to achieve this.

This is the only Section in my .nsi file. The little bit of logic is what I was trying to avoid typing over and over manually, as it is ugly and hard to follow. If there's another way to achieve the same result, I'd be interested to consider that as well. Other syntax, techniques or modules.

Section "-noop"
SetOutPath $INSTDIR

# Logic to Check for Installed and Backups, Rename or Copy
# but never overwrite
IfFileExists "INSTALL.txt" 0 +3
IfFileExists "INSTALL.txt.bak" +3 0 # I B -> !R !C
Rename "INSTALL.txt" "INSTALL.txt.bak" # I !B -> R C
File "INSTALL.txt" # !I B -> !R C - same
# !I !B -> !R C - same
SectionEnd

Example 3.2.2 is broken, the macro should work... (You cannot pass a variable as the file source path/name)


Originally posted by Anders
Example 3.2.2 is broken, the macro should work... (You cannot pass a variable as the file source path/name)
Ok, thanks for clarifying. Before posting, I tried a pure Function, a pure Macro, and a Hybrid. I must have mistyped the Macro somehow, because it works fine now.

I'm still a bit confused about the parameter passed to the macro not being a variable. Is it that everything that touches the macro, including the parameters, are just copy/pasted internally just before compilation?

Also not sure I understand the reasoning behind the restriction of File not using variables for cases like this. Whether I mistype the string literal now, or mistype a variable name that later references that string literal, it makes little difference. In either case I'd get a file not found error when compiling, and then go fix the typo.

My code here was simple enough for a macro, so it doesn't matter in this case. But if my per-file logic or list of total files got bigger, the macro technique could cause bloat. That'd be a concern. How do people normally work around this?

Anyways, thanks again. Cheers.

A macro can take variables as parameters but the File instruction can not since variables are used at runtime (on the end users machine) and the file instruction needs a filename at compile time (/oname (destination) can use parameters)