0

Modifying code that was shared here in order to make it loop, however on subsequent iterations, the code assumes the first input every time. Probably has to do with delayed expansion but I don't know how to fix it?

@echo off
setlocal EnableDelayedExpansion

rem Execute a SET /P command with time out
rem Antonio Perez Ayala
rem Modified

rem If this file is re-executed as pipe's right side, go to it
if "%~1"=="TimeoutMonitor" goto %1

:Loop

del InputLine.txt 2> NUL
(
   set /P "input=You have 3 seconds to type yes or no: " > CON
   > InputLine.txt call set /P "=%%input%%" < NUL
) 2> NUL | "%~F0" TimeoutMonitor 3
set /P "input=" < InputLine.txt
del InputLine.txt
if /I "%input%"=="no" echo You typed no
if /I "%input%"=="yes" echo You typed yes
PING -n 3 127.0.0.1>nul

goto :Loop


: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

Sample input and output:

You have 3 seconds to type yes or no: yes
You typed yes
You have 3 seconds to type yes or no: no
You typed yes
servicecli
  • 95
  • 9
  • 2
    Please use `If /I "%input%" == "` not `if /I "%input%" equ "`, you're comparing strings, not numbers. Don't forget to do the same here, `if "%~1" equ "TimeoutMonitor"`. You should also reset the value of `%input%` at the start of `:Loop`. – Compo Jun 04 '19 at 20:53
  • Try simple `echo You typed "%input%"` instead two **if**s `if /I "%input%"==…`. I'd guess that there are some unwanted (leading or trailing?) spaces in the `%input%` value (you can obtain something like `You typed "no "`. – JosefZ Jun 04 '19 at 21:14
  • Compo is right, `set "input="` must be placed after `:Loop`. I also don't understand what the command `PING -n 3 127.0.0.1` in your loop is for as there is already a delay established in the `:TimeoutMonitor` subroutine. Anyway, since you only seem to need a yes/no decision, you could use [`choice`](https://ss64.com/nt/choice.html), which does not allows invalid input and features a timeout: `choice /M "You have 3 seconds to select [Y]es or [N]o:" /C YNC /N /T 3 /D C`... – aschipfl Jun 06 '19 at 16:43
  • The procedure to determine the PID of the left-side `cmd` instance (`set /P` prompt) of the pipe `|` in the `:TimeoutMonitor` subroutine is a bit dangerous, because the next-to-last `cmd` process returned by `tasklist` is taken to be aborted after the timeout, which is not guaranteed to really be the intended process, particularly when some other stuff runs in parallel that uses `cmd` too... – aschipfl Jun 06 '19 at 16:51

0 Answers0