如何在一定时间后退出SET /p命令?例如,如果用户输入时间太长,我希望退出SET /p。
@echo off
setlocal EnableDelayedExpansion
rem Execute a SET /P command with time out
rem Antonio Perez Ayala
rem If this file is re-executed as pipe's right side, go to it
if "%~1" equ "TimeoutMonitor" goto %1
del InputLine.txt 2> NUL
(
set /P "line=You have 10 seconds to complete this input: " > CON
> InputLine.txt call set /P "=%%line%%" < NUL
) 2> NUL | "%~F0" TimeoutMonitor 10
set /P "line=" < InputLine.txt
del InputLine.txt
echo Line read: "!line!"
goto :EOF
:TimeoutMonitor
rem Get the PID of pipe's left side
tasklist /FI "IMAGENAME eq cmd.exe" /FO TABLE /NH > tasklist.txt
for /F "tokens=2" %%a in (tasklist.txt) do (
set "leftSidePipePID=!lastButOnePID!"
set "lastButOnePID=%%a"
)
del tasklist.txt
rem Wait for the input line, or until the number of seconds passed
for /L %%i in (1,1,%2) do (
ping -n 2 localhost > NUL
if exist InputLine.txt exit /B
)
rem Timed out: kill the SET /P process and create a standard input line
taskkill /PID %leftSidePipePID% /F > NUL
echo/
echo Timed Out> InputLine.txt
exit /B
choice
来接受单个字符并设置等待超时时间。@if (@CodeSection == @Batch) @then
@echo off
rem Give the desired wait time in milliseconds:
start "" /B Cscript //nologo //E:JScript "%~F0" 10000
set "input=Time out"
set /P "input=You have 10 seconds to complete this input: "
echo Input read: %input%
goto :EOF
@end
WScript.Sleep(WScript.Arguments(0));
WScript.CreateObject("WScript.Shell").SendKeys("{ENTER}");
如果允许使用可下载工具,则可以使用 editv64.exe(64 位)或 editv32.exe(32 位),并带上 -t
参数。例如:
editv64 -p "Enter something within 10 seconds: " -t 10 INP
这个工具还有其他的优点,比如在输入时隐藏输入字符串(-m
),以及可以交互地编辑现有的环境变量。你可以在这里下载:
Start Call "%~dp0TimoutMonitor" "needlessArg"
的方法吧?对我来说,使用Start Call
一直是最稳定的异步运行文件的方式,但是如果是通过这种方式调用,它如何返回输入的值呢?在一些有限的测试中,我没有看到set /p
单独打开一个新的CMD
实例以获取最新的PID
。 - k1dfr0stdset /p
和> InputLine.txt
放在括号()
内的“命令块”(如果你愿意这样称呼它)导致整个块被管道传输到文件本身中,不管怎样...?并且将stdOut
发送到CON
- 即使对于set /P
命令也是如此 - 这允许CON(sole)
保持set /P
的处理同时保持环境?请参阅https://ss64.com/nt/con.html - 希望我接近理解这个特性。非常非常酷。 - k1dfr0stdCON
设备存储在管道输出中的新实例CMD
中作为暂存区,管道的第二部分调用自身以进行计时器,杀死存储在_CON_中的管道实例的CMD
并允许块外的行(set /P "line=" < InputLine.txt
)...而且 - 由于第一个set /p
被存储在CON
中,这就是CMD
解释器如何从起始批处理环境中返回第一个set /p
的值,因为它是从内部调用的...更接近了吗?2> Nul用于消除管道中的错误。 - k1dfr0std