批处理文件中的“choice”命令的errorlevel返回值为0。

10
我正在尝试创建一个批处理文件,根据操作系统的版本执行不同的“choice”命令。在 Windows 7 和 Windows XP 中,“choice”命令的语法不同。
“choice”命令返回1表示Y,2表示N。下面的命令会返回正确的错误级别:
对于 Windows 7:
choice /t 5 /d Y /m "Do you want to automatically shutdown the computer afterwards "
echo %errorlevel%
if '%errorlevel%'=='1' set Shutdown=T
if '%errorlevel%'=='2' set Shutdown=F

Windows XP:

choice /t:Y,5 "Do you want to automatically shutdown the computer afterwards "
echo %ERRORLEVEL%
if '%ERRORLEVEL%'=='1' set Shutdown=T
if '%ERRORLEVEL%'=='2' set Shutdown=F

然而,当它与检测Windows操作系统版本的命令结合使用时,在我的Windows XP和Windows 7代码块中,无论在选择命令之前还是之后,errorlevel都会返回0。

REM Windows XP
ver | findstr /i "5\.1\." > nul
if '%errorlevel%'=='0' (
set errorlevel=''
echo %errorlevel%
choice /t:Y,5 "Do you want to automatically shutdown the computer afterwards "
echo %ERRORLEVEL%
if '%ERRORLEVEL%'=='1' set Shutdown=T
if '%ERRORLEVEL%'=='2' set Shutdown=F
echo.
)

REM Windows 7
ver | findstr /i "6\.1\." > nul
if '%errorlevel%'=='0' (
set errorlevel=''
echo %errorlevel%
choice /t 5 /d Y /m "Do you want to automatically shutdown the computer afterwards "
echo %errorlevel%
if '%errorlevel%'=='1' set Shutdown=T
if '%errorlevel%'=='2' set Shutdown=F
echo.
)

如您所见,我甚至在执行choice命令之前尝试清除errorlevel变量,但是在执行choice命令后,errorlevel仍然保持为0。

有什么建议吗? 谢谢!

1个回答

21
你遇到了一个经典问题 - 你试图在代码的括号块中扩展 %errorlevel%。这种扩展形式在解析时发生,但整个 IF 结构一次性解析,所以 %errorlevel% 的值不会改变。
解决方案很简单 - 延迟扩展。你需要在顶部使用 SETLOCAL EnableDelayedExpansion,然后使用 !errorlevel!。延迟扩展发生在执行时,因此你能够看到括号内值的更改。
SET 的帮助文档 (SET /?) 描述了关于 FOR 语句的问题和解决方案,但概念是相同的。
你还有其他选项。
你可以将代码从 IF 的主体移动到没有括号的标记代码段,并使用 GOTOCALL 访问代码。然后你可以使用 %errorlevel%。我不喜欢这个选项,因为 CALLGOTO 相对较慢,而且代码不够优雅。
另一个选择是使用 IF ERRORLEVEL N 而不是 IF !ERRORLEVEL!==N。 (见 IF /?) 因为 IF ERRORLEVEL N 测试 errorlevel 是否 >= N,所以你需要按降序进行测试。
REM Windows XP
ver | findstr /i "5\.1\." > nul
if '%errorlevel%'=='0' (
  choice /t:Y,5 "Do you want to automatically shutdown the computer afterwards "
  if ERRORLEVEL 2 set Shutdown=F
  if ERRORLEVEL 1 set Shutdown=T
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接