我在Windows上运行的Qt程序遇到了一个奇怪的错误。该程序使用QProcess生成具有两个参数的子进程。传递给QProcess :: start()方法的程序和参数的格式为:
"batchfile.bat" "--option1=some_value" "--option2=some_other_value\with_a\path"
由于某些原因,当这些选项进入批处理文件进行处理时,等号已转换为空格,现在看起来像:
"batchfile.bat" "--option1 some_value" "--option2 some_other_value\with_a\path"
因此,处理失败。什么可能导致等号被空格取代的想法?我正在使用Qt下载页面上的QT 4.6.3框架的mingw构建。
编辑: 这是实际的代码。我没有写它(我是一个完整的Qt noob)但我必须尝试让它工作。它是在两个版本的RHEL(4和5),OS X和Windows上运行的自动构建系统的一部分。除了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";
转换为Windows的actaul值(在第一个qDebug()打印调用中打印出来的位)是:
DEBUG:启动scons进程:“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“
然而在scons-1.3.0.bat中(我让它回显了所有执行的命令)传递的参数如下:
“ - 变种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“
缺少等号。
编辑(6/29/10): 我应该补充一点,该系统设计为使用LSF批处理排队系统在小型Windows批处理场上运行。它仅在进程作为批处理作业运行时失败。当我从其中一台批处理机器上的命令行运行这个程序时,它可以完美地工作并完全按照预期的方式运行。所以这可能是一个环境问题。
答案 0 :(得分:0)
您是否尝试过转移=
标志?此外,示例中的路径肯定需要转义\
字符。
答案 1 :(得分:0)
这很可能是因为引号没有通过(它们可能需要转义,请参阅docs for QProcess::start())。
cmd.exe将命令行选项中的等号视为未引用为类似于空格或制表符的参数之间的分隔符。只是Windows cmd脚本中很多奇怪之处:</ p>
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"
我遇到的关于如何在Windows cmd脚本中处理命令行参数的最佳文档是Tim Hill's "Windows NT Shell Scripting" - 只使用一分钱!
根据您的更新中提供的示例,我认为您可能希望您的选项具有等于其中的符号,并在其中嵌入引号:
"\"--variant=%1-%2\""
"\"--source-release=%1\""
以下脚本有一个例程,它将从传递给cmd脚本的参数中删除引号。该例程使用上面提到的Tim Hill的书中的成语/技术,在名为RET
的环境变量中返回'dequoted'参数。我从这里的一个例子中偷走了一些dequoting代码:http://ss64.com/nt/syntax-esc.html,但是它使得处理空引号更加健壮。
@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
这就是为什么你要避免(在我看来)除了最简单的任务之外的cmd脚本。但是,我希望这可以帮助您通过批处理文件将不带引号的参数传递给您的scons进程。