代码之家  ›  专栏  ›  技术社区  ›  dagorym

为什么qProcess将我的参数中的“=”转换为空格?

  •  0
  • dagorym  · 技术社区  · 14 年前

    我在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上的自动构建系统的一部分。除了窗户,它在任何地方都能正常工作。

    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()print调用中输出的位)是:

    调试:启动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(我让它回送所有执行的命令)中,传递的参数如下所示:

    “--variant windows-i386-32bit-vc71-debug”“--源版本v:\glast\toaster\releasemanagerbuild\windows-i386-32bit-vc71\debug\sciencetools\latest-1-3163\sciencetools-latest-1-3163-source.zip”

    缺少等号。

    编辑(6/29/10) : 我应该补充一点,这个系统是为使用LSF批处理队列系统在一个小的Windows批处理场上运行而设计的。只有当进程作为批处理作业运行时,它才会失败。当我在一台批处理机器上的命令行中运行这个程序时,它工作得很好,完全按照它应该做的做。所以可能是环境问题。

    2 回复  |  直到 14 年前
        1
  •  0
  •   Michael Burr    14 年前

    这很有可能是因为引用没有通过(它们可能需要转义,请参见 docs for QProcess::start() )

    cmd.exe在命令行选项中处理等号,这些等号在类似于空格或制表符的参数之间不作为分隔符引用。在windows cmd脚本中有很多奇怪之处:

    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\""
    

    编辑--新材料

    下面的脚本有一个例程,它将除去传递给命令脚本的参数的引号。例程返回名为的环境变量中的“dequoted”参数。 RET 使用上面提到的TimHill的书中的一个习语/技巧。我从这里的一个例子中偷了一些去引用的代码: 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
    

    这就是为什么你想要避免(在我看来)命令脚本除了最简单的任务。但是,我希望这能帮助您通过批处理文件将未引用的参数传递给scons进程。

        2
  •  0
  •   bluebrother    14 年前

    你试过逃离 = 标志?另外,您例子中的路径肯定需要从 \ 性格。