views:

138

answers:

2

I've run into a weird error with a Qt program running on Windows. The program uses QProcess to spawn a child process wit two arguments. The program and arguments passed to the QProcess::start() method are of the form:

"batchfile.bat" "--option1=some_value" "--option2=some_other_value\with_a\path"

For some reason by the time those options get to the batchfile for processing the equals signs have been converted to spaces and it now looks like:

"batchfile.bat" "--option1 some_value" "--option2 some_other_value\with_a\path"

because of this, the processing fails. Any ideas what could be causing the equal signs to be replaced by spaces? I'm using the mingw build of the QT 4.6.3 framework found on the Qt download page.

EDIT: Here's the actual code. I didn't write it (I'm a complete Qt noob) but I've got to try to get it working. It's part of an automated build system that runs on two versions of RHEL (4 and 5), OS X, and Windows. And it works fine everywhere but Windows.

QProcess sconsProcess;
sconsProcess.setWorkingDirectory(build.getBuildLocation());
sconsProcess.setProcessChannelMode(QProcess::MergedChannels);

qDebug()<<"Starting scons process:"<<build.getSconsLocation()<<QString("--variant=%1-%2").arg(build.getOs()).arg(build.getVariant())<<
          QString("--source-release=%1").arg(build.getSettings().getSetting("sourceReleaseLocation", QStringList()<<"BUILDLOCATION"<<"VERSION",
                    QStringList()<<build.getBuildLocation()<<build.getBuildPackage().getVersion()).toString());
sconsProcess.start(build.getSconsLocation(), QStringList()<<QString("--variant=%1-%2").arg(build.getOs()).arg(build.getVariant())<<
          QString("--source-release=%1").arg(build.getSettings().getSetting("sourceReleaseLocation", QStringList()"BUILDLOCATION"<<"VERSION",
                    QStringList()<<build.getBuildLocation()<<build.getBuildPackage().getVersion()).toString()));
qDebug()<<"Source release build process started";

The actaul values that translates into in Windows (the bit that gets printed out in the first qDebug() print call) is:

DEBUG: Starting scons process: "V:\Glast_Software\Toaster\tools\Python2.5\Scripts\scons-1.3.0.bat" "--variant=Windows-i386-32bit-vc71-Debug" "--source-release=V:\Glast_Software\Toaster\ReleaseManagerBuild\Windows-i386-32bit-vc71\Debug\ScienceTools\LATEST-1-3163\ScienceTools-LATEST-1-3163-source.zip"

However inside the scons-1.3.0.bat (I had it echo all the commands executed) the passed parameters look like:

"--variant Windows-i386-32bit-vc71-Debug" "--source-release V:\Glast_Software\Toaster\ReleaseManagerBuild\Windows-i386-32bit-vc71\Debug\ScienceTools\LATEST-1-3163\ScienceTools-LATEST-1-3163-source.zip"

with the equal signs missing.

EDIT (6/29/10): I should add that this system is designed to run on a small Windows batch farm using the LSF batch queuing system. It only fails when the process is running as a batch job. When I run this program from the command line on one of the batch machines, it works perfectly and does exactly what it is supposed to do. So maybe it is an environment problem.

A: 

Have you tried escaping the = signs? Also, the paths in your example surely need escaping of the \ character.

bluebrother
I should try that but the code is compiled on RHEL4, RHEL5, OS X 10.4 and Windows. Would escaping the '=' cause a problem on the unix builds? (the value of the entry with the path in it is pulled from a configuration stored in MySQL and it seems to be coming out okay without extra escapes).
dagorym
Ok, so you don't pass the strings literally as stated in your original question. Please refine your question then, it looks like you want to pass a string with unescaped backslashes (which as a literal string would be wrong for the compiler).
bluebrother
Escaping the equals signs had exactly zero effect. :(
dagorym
A: 

There's a good chance that this is because the quotes aren't making it through (they may need to be escaped, see the docs for QProcess::start()).

cmd.exe treats equals signs in command line options that aren't quoted as a separator between arguments similar to a space or tab. Just one of very many bits of oddness in Windows cmd scripting:

C:\test>type c:\util\cmdechoargs.cmd
@echo off
setlocal
set /a i=0
echo args[*]: %*
:loop
if {%1} == {} goto :eof
echo argv[%i%]: %1
set /a i=%i% + 1
shift
goto :loop


C:\test>cmdechoargs testing=123
args[*]: testing=123
argv[0]: testing
argv[1]: 123

C:\test>cmdechoargs "testing=123"
args[*]: "testing=123"
argv[0]: "testing=123"

The best documentation I've come across for how to handle command line arguments in Windows cmd scripts is Tim Hill's "Windows NT Shell Scripting" - get one used for only a penny!

Based on the examples given in your update, I think you might want your options that have equals signs in them to have quotes embedded inside them:

"\"--variant=%1-%2\""
"\"--source-release=%1\""

Edit -- new material

The following script has a routine that will strip the quotes off of an argument passed to a cmd script. The routine returns the 'dequoted' argument in an environment variable named RET using an idiom/technique from Tim Hill's book I mentioned above. I stole some of the dequoting code from an example here: http://ss64.com/nt/syntax-esc.html, but made it a bit more robust to handle empty quotes.

@echo off
setlocal
set /a i=0
echo args[*]: %*
:loop
if {%1} == {} goto :eof
echo.
echo argv[%i%]: %1

call :dequote %1
set dequoted_arg=%RET%
echo argv[%i%] ^(dequoted^): %dequoted_arg%

set /a i=%i% + 1
shift
goto :loop


:dequote
setlocal
SET _string=###%1###
if {%_string%} == {######} goto :dequote_empty
if {%_string%} == {###""###} goto :dequote_empty
SET _string=%_string:"###=%
SET _string=%_string:###"=%
SET _string=%_string:###=%
goto :dequote_done

:dequote_empty
set _string=

:dequote_done
endlocal & (set RET=%_string%) & goto :eof

This kind of thing is why you want to avoid (in my opinion) cmd scripts except for the simplest of tasks. But, I hope this helps you pass unquoted arguments to your scons process through your batch file.

Michael Burr
I'm trying exactly that right now.
dagorym
And it didn't work adding an extra set of escaped quotes around the arguments did manage to turn it into a single argument and the = sign didn't vanish but the quotes then got passed along to SCons and it thought the whole thing was a build target instead of an option and value.
dagorym
@dagorym: I've added an example that can strip the quotes off the batch file arguments in your cmd script. I hope it helps...
Michael Burr
I was able to use this to solve the problem. Thanks. And in the process of just getting it to work figured out another problem with the execution environment that I now have to run down. :)
dagorym