与Windows快捷方式相比​​,在DOS提示符下的if语句中,DOS环境设置的不同行为 [英] Different behaviour of DOS Environment setting, in if statement, in DOS prompt as compared to Windows Shortcut

查看:86
本文介绍了与Windows快捷方式相比​​,在DOS提示符下的if语句中,DOS环境设置的不同行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这看起来很简单,但事实证明真是太痛苦了.

在Windows 7上,我可以将以下内容粘贴到命令提示符中,并将其设置为%programfiles%%programfiles(x86)%,然后回显它的设置:

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

但是,当将相同的命令放入快捷方式时,我得到了:

> >

这是怎么回事?

解决方案

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

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条对两个上下文均有效.以下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 . . .

This seems so simple, but has turned out to be such a pain.

On Windows 7, I can paste the below into a command prompt and have it set ProgramFiles(x32) to either %programfiles% or %programfiles(x86)% then echo what it was set to:

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

However when putting this same command into a shortcut, I get this:

What is going on?

解决方案

First I'll start from the perspective of running your code from the command prompt. You have 4 problems with your code in that context.

1) I don't think this makes much difference, but I believe you always want to execute the last 3 commands in your command line. But you used the conditional && operator which only executes the following command if the preceding command was successful. I believe you want to use & instead.

2) You have a precedence problem. You want to execute an IF/ELSE statement, then when it has completed you want to execute 3 additional commands. But your 3 additional commands as written are considered to be part of the ELSE clause of the IF statement. You need an extra set of parentheses around the entire IF/ELSE statement.

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

3) You want everything after %comspec% /c to be part of the command line that is passed to CMD.EXE. But when you run your entire statement in a command line console the call to CMD.EXE ends at the first appearance of &. The remainder of the line is executed by the parent command window, not by your call to CMD.EXE. You need to either escape the & characters as ^&, or else quote the entire line that is to be passed.

4) %VAR% expansion occurs when a line is parsed, and the entire command line is parsed at one time before any of the commands are executed. So the value of %ProgramFiles(x32)% that you see is the value before any of the commands are executed. The value is normally not defined, and you are in a command line context, so the original string with the percents is printed. The fix is to either use CALL ECHO %^ProgramFiles(x32)% or else enable delayed expansion with the /V:ON option and use ECHO !ProgramFiles(x32)!. The caret is to ensure that the string is passed to CMD.EXE and not expanded in your parent command line (just in case ProgramFiles(x32) is already defined).

Each of the following should give the result you are looking for from a command prompt:

%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


The situation is a bit different when executed from a shortcut. The shortcut does not have a parent command prompt, so the point 3) above does not apply. The & characters should not be escaped, though the entire command line may still be quoted.

Points 1, 2, and 4 are still valid for the shortcut.

So the following statements will all work as a shortcut:

%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


Comparing the 2 sets of statements, only 2 of them are valid for both contexts. The following 2 statements will work both on the command line and in a shortcut:

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

Both statements above give the following result when issued from a Command Prompt or as a shortcut on my Vista machine:

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 . . .

这篇关于与Windows快捷方式相比​​,在DOS提示符下的if语句中,DOS环境设置的不同行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆