如何阻止 Windows 命令解释器在用户输入不正确时退出批处理文件? [英] How to stop Windows command interpreter from quitting batch file execution on an incorrect user input?

查看:26
本文介绍了如何阻止 Windows 命令解释器在用户输入不正确时退出批处理文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有以下示例代码:

If I have the following example code:

@echo off
:menu
cls
echo 1. win
echo 2. lose
set /p menu=
goto %menu%
pause>nul

:win
cls
echo yay lolz
pause>nul

:lose
cls
echo really?
pause>nul

如果我输入test"而不是有效响应,我该如何阻止批次退出?

How do I stop the batch from quitting if I type "test" instead of a valid response?

推荐答案

首先,我建议在浏览器中添加书签:

First, I suggest to bookmark in your browser:

  • Microsoft's command-line reference
  • An A-Z Index of the Windows CMD command line (SS64)

您可以通过在命令提示符窗口中运行以 /? 作为参数的命令来获取每个 Windows 命令的帮助,例如 if/?, set/?, ...

You can get help for every Windows command by running in a command prompt window the command with /? as parameter, for example if /?, set /?, ...

第二,如果用户应该选择几个选项之一,不要使用 set/p.在提示用户输入字符串并将其分配给环境变量时,必须考虑多个事实:

Second, don't use set /p if the user should choose one of several options. There are multiple facts which must be taken into account on prompting user for entering a string and assigning it to an environment variable:

  1. 关于 set/P "MyVar=Your choice: " 环境变量 MyVar 的使用,如果用户故意或错误按下,不会被修改只需 RETURNENTER.这意味着如果环境变量 MyVar 在用户提示之前没有定义,在用户提示完成后,只需按 RETURN 键,它仍然没有定义.如果在用户提示之前已经定义了 MyVar,它会保持其值不变,以防用户按 RETURNENTER.

  1. On usage of set /P "MyVar=Your choice: " the environment variable MyVar is not modified if the user presses intentionally or by mistake just RETURN or ENTER. This means if the environment variable MyVar is not defined already before the user prompt, it is still not defined after user prompt finished with just hitting key RETURN. And if MyVar is defined already before user prompt, it keeps its value unmodified in case of user presses just RETURN or ENTER.

用户可以在提示 set/P 时自由输入任何字符串.批处理文件编写器无法控制用户真正输入的内容.因此,批处理文件编写器必须考虑到用户错误地或故意输入了一个字符串,该字符串可能会因语法错误而导致批处理文件执行退出,或者它所做的事情与定义的完全不同.

The user has the freedom to type any string on being prompted with set /P. The batch file writer has no control on what the user really enters. So the batch file writer must take into account that the user enters by mistake or intentionally a string which could result in an exit of batch file execution because of a syntax error, or it does something completely different as it is defined for.

一个简单的例子:

@echo on
:MainMenu
@set /P "menu=Your choice: "
if %menu% == 1 goto Label1
if %menu% == 2 goto Label2
goto MainMenu

:Label1
@echo Option 1 was chosen, fine.
goto :EOF

:Label2
@echo Option 2 was chosen, okay.

这个带有 echo on 而不是 echo off 顶部的批处理文件是从命令提示符窗口中启动的,用于调试.

This batch file with echo on instead of echo off at top is started from within a command prompt window for debugging purposes.

在第一次运行时在用户提示下按下 RETURN.Windows 命令解释器退出批处理,因为第一个 IF 条件在执行 IF 命令之前被预处理:

Just RETURN is pressed on user prompt on first run. Windows command interpreter exits batch processing because first IF condition is preprocessed before execution of IF command to:

if  == 1 goto Label1

显然缺少第一个参数.cmd.exe 遇到此语法错误并退出批处理并显示相应的错误消息.原因是环境变量menu没有定义,在用户提示之前没有定义,在用户提示之后也没有定义.

There is obviously missing the first argument. cmd.exe encounters this syntax error and exits batch processing with an appropriate error message. The reason is the missing definition of environment variable menu which is not defined before user prompt and is still not defined after user prompt.

字符串 2 是在命令提示符窗口中第二次运行批处理文件时输入的,批处理文件按预期工作.

The string 2 is entered on second run of the batch file from within command prompt window and the batch file works as expected.

在同一命令提示符窗口中第三次运行批处理文件时,只需在用户提示符下按下 RETURN.批处理文件再次输出第二条消息.为什么?环境变量 menu 仍然是在第二个批处理文件执行时使用该字符串定义的,并且在按下 RETURN 时未修改该变量.

On third run of the batch file from within same command prompt window again just RETURN is pressed on user prompt. The batch file outputs again the second message. Why? The environment variable menu is still defined from second batch file execution with that string and the variable was not modified on pressing RETURN.

好的,让我们将示例批处理文件修改为:

Okay, let us modify the example batch file to:

@echo on
:MainMenu
@set "menu=2"
@set /P "menu=Your choice: "
if "%menu%" == "1" goto Label1
if "%menu%" == "2" goto Label2
goto MainMenu

:Label1
@echo Option 1 was chosen, fine.
goto :EOF

:Label2
@echo Option 2 was chosen, okay.

这已经更好了,因为现在环境变量 menu 总是用值 2 预定义.所以如果用户什么都不输入,就会跳转到 Label2.此外,变量 menu 上次运行的值对批处理文件的执行不再有影响.

This is already better as now environment variable menu is always predefined with value 2. So if the user enters nothing, a jump to Label2 is done. Also the value of previous run of variable menu has no effect anymore on execution of batch file.

但是现在真的安全和故障安全吗?

But is that really secure and fail safe now?

不,它不是.用户仍然可以错误地输入错误的字符串.

No, it isn't. The user still can enter by mistake a wrong string.

例如,用户错误地输入了 " 而不是 2,这在德语键盘上很容易,如 CapsLock+2Shift+2 导致输入 ".预处理后的第一个 IF 命令行现在是:

For example the user enters by mistake " instead of 2 which is easy on German keyboards as CapsLock+2 or Shift+2 results in entering ". The first IF command line after preprocessing is now:

if """ == "1" goto Label1

这又是一个无效的命令行,导致由于语法错误而退出批处理文件.

And this is again an invalid command line resulting in an exit of batch file processing because of a syntax error.

假设用户在提示时输入字符串:

Let us assume a user enters on prompt the string:

" == "" call dir "%USERPROFILE%Desktop" & rem 

注意:末尾有一个空格.

第一个 IF 条件被 Windows 命令解释器预处理为:

The first IF condition is preprocessed by Windows command interpreter to:

if "" == "" call dir "%USERPROFILE%Desktop"   & rem " == "1" goto Label1

可以看出,批处理文件现在在两种IF条件下都执行了一个根本没有写入批处理文件的命令.

It can be seen that the batch files executes now a command not written in the batch file at all on both IF conditions.

如何让用户提示失败安全可靠?

How to get a user prompt fail safe and secure?

至少在评估用户输入字符串的代码周围使用延迟环境变量扩展.

By using delayed environment variable expansion at least around code evaluating the user input string.

@echo on
:MainMenu
@setlocal EnableDelayedExpansion
@set "menu=2"
@set "Label=MainMenu"
@set /P "menu=Your choice: "
if "!menu!" == "1" set "Label=Label1"
if "!menu!" == "2" set "Label=Label2"
endlocal & goto %Label%

:Label1
@echo Option 1 was chosen, fine.
goto :EOF

:Label2
@echo Option 2 was chosen, okay.

现在用户输入字符串不再修改由 Windows 命令解释器执行的命令行.因此,不再可能由于用户输入导致的语法错误而退出批处理文件处理.并且批处理文件永远不会执行未写入批处理文件的命令.

Now the user input string does not modify anymore the command lines executed by Windows command interpreter. So an exit of batch file processing because of a syntax error caused by user input is not possible anymore. And the batch file never executes commands not written in batch file.

第三,对于简单的选择菜单,有一个比 set/P 更好的命令 - 选择.

Third, there is a better command than set /P for a simple choice menu – CHOICE.

@echo off
:MainMenu
cls
echo/
echo    1 ... Option 1
echo    2 ... Option 2
echo    E ... Exit
echo/
%SystemRoot%System32choice.exe /C 12E /N /M "Your choice: "
if errorlevel 3 goto :EOF
if errorlevel 2 goto Label2
if not errorlevel 1 goto MainMenu

@echo Option 1 was chosen, fine.
goto :EOF

:Label2
@echo Option 2 was chosen, okay.

用户不再有自由输入批处理文件编写器未定义的内容.在用户按下 12eShift+E 后,批处理文件会立即继续.choice 会忽略除 Ctrl+C 之外的所有其他内容.

The user has no freedom anymore to enter something not defined by batch file writer. The batch file continues immediately after the user has pressed either 1, 2, e or Shift+E. Everything else is ignored by choice with exception of Ctrl+C.

动态变量 ERRORLEVEL 具有三个选项,在 choice 终止后,几乎总是一个 1 到 3 范围内的值,返回 1 到 3 作为调用 的退出代码cmd.exe.例外情况是批处理文件的用户在提示时按下 Ctrl+C 并回答下一个提示 Terminate batch job (Y/N)? 的罕见用例code>cmd.exe 和 N.在这种情况下,动态变量 ERRORLEVEL 的值是 0,这也是 if not errorlevel 1 goto MainMenu 处理这个非常特殊的用途的原因案例.

The dynamic variable ERRORLEVEL has with three options nearly always a value in range 1 to 3 after choice terminated with returning 1 to 3 as exit code to calling cmd.exe. The exception is the rare use case that the user of a batch file pressed Ctrl+C on prompt and answers the next prompt Terminate batch job (Y/N)? of cmd.exe with N. In this case the dynamic variable ERRORLEVEL has the value 0 which is the reason for if not errorlevel 1 goto MainMenu to handle also this very special use case.

注意: if errorlevel X 表示IF GREATER OR EQUAL X.所以总是有必要从命令 choice 的最高可能退出代码开始.

Note: if errorlevel X means IF GREATER OR EQUAL X. So it is always necessary to start with highest possible exit code of command choice.

由于分配给 ERRORLEVEL 的退出代码是众所周知的,因此可以在较大的菜单上通过使用适当的标签进一步优化代码:

As the exit code assigned to ERRORLEVEL is well known, it is possible on larger menus to optimize the code further by using appropriate labels:

@echo off
:MainMenu
cls
echo/
echo    1 ... Option 1
echo    2 ... Option 2
echo    E ... Exit
echo/
%SystemRoot%System32choice.exe /C 12E /N /M "Your choice: "
goto Label%ERRORLEVEL%

:Label0
rem The user pressed Ctrl+C and on next prompt N and
rem so made no choice. Prompt the user once again.
goto MainMenu

:Label1
@echo Option 1 was chosen, fine.
goto :EOF

:Label2
@echo Option 2 was chosen, okay.
goto :EOF

:Label3

命令CHOICE的使用可以使选择菜单的编码变得非常简单.

The usage of command CHOICE can make choice menus very simple to code.

另见:我如何制作你确定"吗?Windows 批处理文件中的提示?

第四,另见我在GOTO :EOF 返回何处的回答?

这篇关于如何阻止 Windows 命令解释器在用户输入不正确时退出批处理文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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