NSIS is an open source installer builder which works under Windows and Unix.
One of the problems with using macros/push/pop is that the quotes can conflict with each other. To avoid this I’ve found that standardising your quoting is important in order to avoid problems especially with nested calls.
The example below shows how a perfectly reasonable piece of
NSIS code might unexpectedly not compile. Can you spot the mistake?
Name "NsExec Function Test"
OutFile "nsexecTest.exe"
!macro doMessage WHAT
MessageBox MB_OK '${WHAT}'
!macroend
!define doMessage '!insertmacro doMessage'
Section
${doMessage} "hello it's me"
SectionEnd
The doMessage is a macro which is substituted and not called, so the translations go thus:
${doMessage} “hello it’s me”
!insertmacro doMessage “hello it’s me”
MessageBox MB_OK ‘hello it’s me’
As you can see we have an invalid call to
MessageBox
because there are unmatched quotes. In order to overcome this problem the caller must know the nature of the quotes inside the code which is being used, and delimit the quote in such a way that it survives the invocation. In this case we must add an additional backslash which itself must be delimited to survive the first set of parsing. The section must be changed to:
Section
${doMessage} "hello it$\'s me"
SectionEnd
so that by the time it gets translated we have:
MessageBox MB_OK ‘hello it\’s me’
Most people use double quotes to surround text because it allows you to use single quotes more easily.
However, there is a big problem if you are using NSIS and Windows. Bill in all his wisdom created DOS which has the most ridiculously complicated syntax when it comes to handling quotes [try typing
cmd /?
if you don’t believed me!]. Then he said you could have spaces in file names which you can only delimit by wrapping in double quotes.
Anyway what the hell does this have to do with anything? Glad you asked. In order to create an
NSIS macro that leads to the ability to run a program under Windows you need to preserve double quotes all the way to the end, which means you can’t use double quotes as a parameter wrapper. So consider this code:
Name "NsExec Function Test"
OutFile "nsexecTest.exe"
!macro doAction WHAT
nsexec::exectolog '${WHAT}'
!macroend
!define doAction'!insertmacro doAction'
Section
${doAction} '"c:\fc.exe" "c:\some file1" "c:\some file2" > "c:\some file.out"'
SectionEnd
If you standardise your delivery quotes to always be a single quote and wrap out going calls in single quotes you should be able to avoid a lot of the headaches associated with un-terminated quotes.
Hi david,
Thanks for the article, its a good one.
I am very much new to NSIS and have a doubt.
In one of the existing installers in my organisation I see a statement
StrCpy “$variable1″ “$variable2″
can you explain what is the meaning of using variables inside quotes.
Thanks in advance