Archive: !system and quotes/spaces in the EXE path


!system and quotes/spaces in the EXE path
I'm trying to have my NSIS script compress a file while building the installer. The script looks like this:


!define GZIP "Q:\Third Party Tools\gzip.exe"

!macro GZIPFILE SourceFile CompressedName
!tempfile GZIPTEMP
!system 'copy "${SourceFile}" "${GZIPTEMP}"' = 0
!system '"${GZIP}" -9v "${GZIPTEMP}"' = 0
File "/oname=${CompressedName}" "${GZIPTEMP}.gz"
!delfile "${GZIPTEMP}.gz"
!undef GZIPTEMP
!macroend


If I set "verbose 4", the relevant snippet of output from makensis is as follows:


!system: ""Q:\Third Party Tools\gzip.exe" -9v "C:\DOCUME~1\gknap\LOCALS~1\Temp\nst20C.tmp""
"Q:\Third: No such file or directory
Party: No such file or directory
Tools\gzip.exe": No such file or directory
C:\DOCUME~1\gknap\LOCALS~1\Temp\nst20C.tmp: 95.2% -- replaced with C:\DOCUME~1\gknap\LOCALS~1\Temp\nst20C.tmp.gz
!system: returned 1, aborting


This is weird for a few reasons. First, the path to gzip.exe is being split up even though it's enclosed in quotes. Then, gzip is actually being invoked successfully, but !system returns 1 even though I'm fairly certain that gzip is returning 0.

Is there something wrong with my script, or does this look like an NSIS bug?

I came up with the following workaround:


!system 'start "gzip" /b /wait "${GZIP}" -9v "${GZIPTEMP}"' = 0


Now the output is:


!system: "start "gzip" /b /wait "Q:\Third Party Tools\gzip.exe" -9v "C:\DOCUME~1\gknap\LOCALS~1\Temp\nst170.tmp""
"Q:\Third: No such file or directory
Party: No such file or directory
Tools\gzip.exe": No such file or directory
C:\DOCUME~1\gknap\LOCALS~1\Temp\nst170.tmp: 95.2% -- replaced with C:\DOCUME~1\gknap\LOCALS~1\Temp\nst170.tmp.gz
!system: returned 0


The error messages still appear, but gzip runs to completion, and !system returns 0 as expected. I verified that gzip's return code is not lost by testing the following:


!system 'start "gzip" /b /wait "${GZIP}" -9v "${GZIPTEMP}aaaaa"' = 0


Sure enough, gzip reports that it can't find "nstXXX.tmpaaaa", and !system returns 1.

This is weird. What kind of setup is this? Win2000 or later I'm assuming. Do you have anything in <HKLM|HKCU>\SOFTWARE\Microsoft\Command Processor : AutoRun ? Do you have %comspec% set to something other than cmd.exe?

!system 'set comspec'
!system 'md "c:\aaa bbb ccc"'
!system 'copy "%windir%\system32\cmd.exe" "c:\aaa bbb ccc\"'
!define GZIP "c:\aaa bbb ccc\cmd.exe"
!verbose 4
!system '"${GZIP}" /c exit 666' = 666
!system '"${GZIP}" /c if exist "${GZIP}" exit 667' = 667
!system '"${GZIP}" /c echo "${GZIP}"' = 0
on my XP machine this gives me
!system: "set comspec"
ComSpec=C:\WINDOWS\system32\cmd.exe
!system: returned 0
!system: "md "c:\aaa bbb ccc""
!system: returned 0
!system: "copy "%windir%\system32\cmd.exe" "c:\aaa bbb ccc\""
1 file(s) copied.
!system: returned 0
!define: "GZIP"="c:\aaa bbb ccc\cmd.exe"
!system: ""c:\aaa bbb ccc\cmd.exe" /c exit 666"
!system: returned 666
!system: ""c:\aaa bbb ccc\cmd.exe" /c if exist "c:\aaa bbb ccc\cmd.exe" exit 667"
!system: returned 667
!system: ""c:\aaa bbb ccc\cmd.exe" /c echo "c:\aaa bbb ccc\cmd.exe""
"c:\aaa bbb ccc\cmd.exe"
!system: returned 0

I'm speculating here but I think it's because !system is executing under %COMSPEC%

So all Double quotes need dubbed to escape them.

Example:

!system'""${GZIP}""-9v""${GZIPTEMP}""'

I havn't tried this yet myself but some branch in my cerebral cortex is compelling me to accept it as true.

XP SP3.

The Command Processor AutoRun value is nonexistent in HKCU, and empty in HKLM.

ComSpec=C:\WINDOWS\system32\cmd.exe

... I actually can't reproduce the problem exactly as I described it. However, if you set a GZIP environment variable before launching makensis:

set GZIP="Q:\Third Party Tools\gzip.exe"

and then set the GZIP define inside the NSIS script as follows:

!define GZIP `$%GZIP%`

You might also have to whack the enclosing quotes:

!searchreplace GZIP `${GZIP}` '"' ''

Does that change anything?


I don't think the environment variable has anything to do with it. Instead, I think it's something weird happening with macros. Here's a standalone test script.


!macro GZIPTEST
!echo `GZIP is ${GZIP}`
!tempfile GZIPTEMP
!system 'copy "${__FILE__}" "${GZIPTEMP}"' = 0
#!system '"${GZIP}" -9v "${GZIPTEMP}"' = 0
!system 'start "gzip" /b /wait "${GZIP}" -9v "${GZIPTEMP}"' = 0
!delfile "${GZIPTEMP}.gz"
!undef GZIPTEMP
!macroend

!define GZIP "Q:\Third Party Tools\gzip.exe"
!insertmacro GZIPTEST

!undef GZIP
!searchreplace GZIP `$%GZIP%` '%GZIP%' ''

!if `${GZIP}` == '$'
!error "GZIP environment variable is not set"
!endif

!searchreplace GZIP `${GZIP}` '"' ''
!insertmacro GZIPTEST

It gets even more bizarre. If I change the above script as follows:


!define GZIP "C:\Windows\gzip.exe"


When the GZIP environment variable is set as follows:


set GZIP="Q:\Third Party Tools\gzip.exe"


I get this result:


!system: ""C:\Windows\gzip.exe" -9v "C:\DOCUME~1\gknap\LOCALS~1\Temp\nst44C.tmp""
"Q:\Third: No such file or directory
Party: No such file or directory
Tools\gzip.exe": No such file or directory
C:\DOCUME~1\gknap\LOCALS~1\Temp\nst44C.tmp: 47.1% -- replaced with C:\DOCUME~1\gknap\LOCALS~1\Temp\nst44C.tmp.gz
!system: returned 1, aborting


I can't make any sense out of this. In this case, NSIS shouldn't even be looking at that environment variable -- and maybe it isn't; I'm curious to know whether anyone else can reproduce this, or whether it's an issue specific to my PC.

Clearing the environment variable causes !system to return 0, but then, of course, the following test won't run because it requires the environment variable.

I fired up Process Monitor and found that the errors are indeed being generated by gzip, not NSIS. The reason is described in the gzip documentation.

Renaming my "location of gzip.exe" environment variable (to, for example, GZIPEXE) solves the problem.