9

我正在尝试创建一个批处理文件,该文件根据正在执行的 Windows 版本执行不同的“选择”命令。选择命令的语法在 Windows 7 和 Windows XP 之间是不同的。

Choice 命令为 Y 返回 1,为 N 返回 2。以下命令返回正确的错误级别:

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

视窗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 在 AN 之前返回 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 var,但是执行choice 命令后errorlevel 仍然为0。

有小费吗?谢谢!

4

1 回答 1

17

您遇到了一个经典问题 - 您正试图%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
)
于 2011-12-23T13:48:16.317 回答