| « Reporting bugs in Spring Tool Suite (STS) | Using WLAN at home and 3G when out on Nokia N900 » |
Using quotes in NSIS
December 18th, 2009NSIS 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?
Code:
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:
Code:
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:
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.