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

与Windows快捷方式相比,DOS环境设置在if语句中在DOS提示中的不同行为

  •  0
  • user66001  · 技术社区  · 13 年前

    这看起来很简单,但事实证明却是一种痛苦。

    在Windows7上,我可以将以下内容粘贴到命令提示符中并进行设置 ProgramFiles(x32) 至任一 %programfiles% %programfiles(x86)% 然后呼应它的设置:

    %comspec% /c if exist "%programfiles%" (set "ProgramFiles(x32)=%programfiles%") else (set "%ProgramFiles(x32)=%programfiles(x86)%") && set Program && echo %programfiles(x32)% && pause
    

    然而,当将相同的命令放入快捷方式时,我会得到以下信息:

    Command Prompt showing ProgramFiles(x32) was set prior, but is not being seen by subsequent echo

    发生了什么事?

    1 回复  |  直到 13 年前
        1
  •  2
  •   dbenham    13 年前

    首先,我将从从命令提示符下运行代码的角度开始。在这种情况下,您的代码有4个问题。

    1) 我不认为这有多大区别,但我相信您总是希望在命令行中执行最后3个命令。但是你使用了条件 && 仅在前一个命令成功的情况下执行以下命令的操作员。我相信你想用 & 相反

    2) 您有优先级问题。您想要执行一个IF/ELSE语句,然后当它完成时,您想要执行3个额外的命令。但是您编写的3个附加命令被认为是IF语句的ELSE子句的一部分。在整个IF/ELSE语句周围需要一组额外的括号。

    (if exist "%programfiles%" (set "ProgramFiles(x32)=%programfiles%") else (set "ProgramFiles(x32)=%programfiles(x86)%")) & ...
    

    3) 你想要之后的一切 %comspec% /c 作为传递给CMD.EXE的命令行的一部分。但是,当您在命令行控制台中运行整个语句时,对CMD.EXE调用将以 & 。该行的其余部分由父命令窗口执行,而不是由对CMD.EXE的调用执行 & 字符为 ^& ,或者引用要传递的整行。

    4) %VAR%展开发生在解析一行时,并且在执行任何命令之前一次性解析整个命令行。因此,您看到的%ProgramFiles(x32)%的值是执行任何命令之前的值。该值通常未定义,并且您处于命令行上下文中,因此会打印带有百分比的原始字符串。修复方法是使用 CALL ECHO %^ProgramFiles(x32)% 或者使用 /V:ON 选择和使用 ECHO !ProgramFiles(x32)! 。插入符号用于确保字符串被传递到CMD.EXE,而不是在父命令行中展开(以防已经定义ProgramFiles(x32))。

    以下每一项都应提供您从命令提示符中查找的结果:

    %comspec% /v:on /c "(if exist "%programfiles%" (set "ProgramFiles(x32)=%programfiles%") else (set "%ProgramFiles(x32)=%programfiles(x86)%")) & set Program & echo !programfiles(x32)!& pause"
    
    %comspec% /c "(if exist "%programfiles%" (set "ProgramFiles(x32)=%programfiles%") else (set "%ProgramFiles(x32)=%programfiles(x86)%")) & set Program & call echo %^programfiles(x32)%& pause"
    
    %comspec% /v:on /c (if exist "%programfiles%" (set "ProgramFiles(x32)=%programfiles%") else (set "%ProgramFiles(x32)=%programfiles(x86)%")) ^& set Program ^& echo !programfiles(x32)!^& pause
    
    %comspec% /c (if exist "%programfiles%" (set "ProgramFiles(x32)=%programfiles%") else (set "%ProgramFiles(x32)=%programfiles(x86)%")) ^& set Program ^& call echo %^programfiles(x32)%^& pause
    

    从快捷方式执行时,情况有点不同。快捷方式没有父命令提示,因此上述第3)点不适用。这个 & 字符不应转义,尽管整个命令行仍可能被引用。

    点1、2和4对于快捷方式仍然有效。

    因此,以下语句都可以作为快捷方式使用:

    %comspec% /v:on /c "(if exist "%programfiles%" (set "ProgramFiles(x32)=%programfiles%") else (set "%ProgramFiles(x32)=%programfiles(x86)%")) & set Program & echo !programfiles(x32)!& pause"
    
    %comspec% /c "(if exist "%programfiles%" (set "ProgramFiles(x32)=%programfiles%") else (set "%ProgramFiles(x32)=%programfiles(x86)%")) & set Program & call echo %^programfiles(x32)%& pause"
    
    %comspec% /v:on /c (if exist "%programfiles%" (set "ProgramFiles(x32)=%programfiles%") else (set "%ProgramFiles(x32)=%programfiles(x86)%")) & set Program & echo !programfiles(x32)!& pause
    
    %comspec% /c (if exist "%programfiles%" (set "ProgramFiles(x32)=%programfiles%") else (set "%ProgramFiles(x32)=%programfiles(x86)%")) & set Program & call echo %^programfiles(x32)%& pause
    

    比较这两组语句,其中只有两组语句对两种上下文都有效。以下2条语句既可以在命令行中使用,也可以在快捷方式中使用:

    %comspec% /v:on /c "(if exist "%programfiles%" (set "ProgramFiles(x32)=%programfiles%") else (set "%ProgramFiles(x32)=%programfiles(x86)%")) & set Program & echo !programfiles(x32)!& pause"
    
    %comspec% /c "(if exist "%programfiles%" (set "ProgramFiles(x32)=%programfiles%") else (set "%ProgramFiles(x32)=%programfiles(x86)%")) & set Program & call echo %^programfiles(x32)%& pause"
    

    当从命令提示符或作为Vista计算机上的快捷方式发出时,上面的两个语句都会给出以下结果:

    ProgramData=C:\ProgramData
    ProgramFiles=C:\Program Files
    ProgramFiles(x32)=C:\Program Files
    ProgramFiles(x86)=C:\Program Files (x86)
    C:\Program Files
    Press any key to continue . . .