我有一个显然未在条件中正确评估的变量。
方案如下:我创建了一个使用SetLocal EnableExtensions
设置的批处理文件,然后它有一个使用SetLocal EnableExtensions EnableDelayedExpansion
设置的主例程。主例程从一个嵌套的if
语句中调用一个子例程,传递两个参数,结果得到一个变量。被调用的子程序设置为SetLocal EnableExtensions
。
问题在于,在评估返回子例程的变量时,显然未正确评估变量:回显一行并确认为等于零的变量会生成if !variable! EQU 0
语句莫名其妙地返回FALSE
。
以下代码后的更多解释和详细信息。
@echo off
SetLocal EnableExtensions
rem Initialize variables
rem -------------------------------------------------------------------------------
set ErrorStatus=0
set PreConditionOne=1
set PreConditionTwo=1
set ValueOne=50
set ValueTwo=50
rem - Main Routine
rem -------------------------------------------------------------------------------
SetLocal EnableExtensions EnableDelayedExpansion
rem Setting initial values for flag variables, value can be: 0=NO, 1=YES, 2=Not Checked.
set PreCheckFail=2
set ParamsNotEqual=2
rem Prechecks: Preconditions must be met in order to check variables.
echo Checking PreConditions.
if %PreConditionOne%==1 (
echo OK: First PreCondition is met.
echo Checking Second PreCondition.
if %PreConditionTwo%==1 (
echo OK: Second PreCondition is met.
echo Calling subroutine to check if values match.
call :Subroutine %ValueOne% %ValueTwo%
echo Back from subroutine.
echo InLoop: ErrorLevel: %ErrorLevel%, ErrorStatus: %ErrorStatus%, ParamsNotEqual: %ParamsNotEqual%
echo InLoopDelayed: ErrorLevel: !ErrorLevel!, ErrorStatus: !ErrorStatus!, ParamsNotEqual: !ParamsNotEqual!
rem This condition fails to correctly check ParamsNotEqual, it works fine with ErrorLevel.
if !ParamsNotEqual! EQU 0 (
echo OK Parameteres verified successfully.
set PreCheckFail=0
) else (
echo ERROR Parameter verification failed.
set PreCheckFail=1
)
) else (
echo ERROR: Second PreCondition is not met.
set PreCheckFail=1
)
) else (
echo ERROR: First PreCondition is not met.
set PreCheckFail=1
)
echo OutLoop: ErrorLevel: %ErrorLevel%, ErrorStatus: %ErrorStatus%, ParamsNotEqual: %ParamsNotEqual%
echo PreCheckFail: %PreCheckFail%
if %PreCheckFail% EQU 0 (echo "PreCheckFail IS ZERO") else (echo "PreCheckFail NOT ZERO")
endlocal
goto :Finish
:Subroutine
rem Subroutine
rem -------------------------------------------------------------------------------
SetLocal EnableExtensions
set ParamOne=%1
set ParamTwo=%2
echo This is the subroutine.
echo The first parameter passed is: %ParamOne%
echo The second parameter passed is: %ParamTwo%
if "%ParamOne%"=="%ParamTwo%" (
echo OK^! Both variables are equal.
set ParamsNotEqual=0
set ErrorStatus=0
) else (
echo ERROR^! Both variables are different.
set ParamsNotEqual=1
set ErrorStatus=1
)
echo EndSub: ErrorLevel: %ErrorLevel%, ErrorStatus: %ErrorStatus%, ParamsNotEqual: %ParamsNotEqual%
endlocal & set ParamsNotEqual=%ParamsNotEqual% & exit /b %ErrorStatus%
:Finish
endlocal
如果运行此脚本,您将看到子例程正确地将ParamsNotEqual
变量返回为0
,然后echo
行正确显示正常解析变量的值和延迟的:
InLoop: ErrorLevel: 0, ErrorStatus: 0, ParamsNotEqual: 2
InLoopDelayed: ErrorLevel: 0, ErrorStatus: 0, ParamsNotEqual: 0
但是当评估条件if !ParamsNotEqual! EQU 0
时,它就会失败。设置@echo on
并没有澄清任何事情,因为延迟变量在执行时间上被扩展,所以我看不到那里真正被评估的内容。
没有效果的事情会导致失败:
SetLocal EnableExtensions EnableDelayedExpansion
SetLocal EnableExtensions EnableDelayedExpansion
。ParamsNotEqual
变量。==
代替EQU
。 if !ParamsNotEqual! EQU 2
(这是变量的初始值)也会返回FALSE
可能的解决方法:
使用!ErrorLevel!
代替!ParamsNotEqual!
可以正常使用。这看起来是逻辑,因为ErrorLevel是一个系统变量,而不是用户定义的变量。
没有为子程序设置SetLocal
,因此子程序变量不与脚本的其余部分隔离,使主程序自动正常工作。这对我没有意义,但让我觉得这个错误可能是由于在设置if
时从嵌套EnableDelayedExpansion
中调用子例程时使用某种限制,或者使用嵌套的{{ 1}}陈述。
我想继续使用SetLocal
而不是ParamsNotEqual
的值,而且,我希望将子例程中的变量保持为ErrorLevel
。
所以,我的问题:这是一种奇怪的行为,是因为我做错了什么,或者这是命令处理器在设置SetLocal
时处理变量的方式的限制?
任何提示都将不胜感激。如果您需要进一步测试或澄清上述内容,请不要犹豫。非常感谢。
答案 0 :(得分:4)
结果是正确的,因为ParamsNotEqual
不等于0
,因为您将其设置为0<space>
。
这一行包含问题。
endlocal & set ParamsNotEqual=%ParamsNotEqual% & exit /b %ErrorStatus%
您应该始终使用SET
的扩展语法和周围的引号
endlocal & set "ParamsNotEqual=%ParamsNotEqual%" & ...