Waiting a fixed time for restricted user input

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Waiting a fixed time for restricted user input

#1 Post by sambul35 » 19 Feb 2016 12:48

Hello guys,

A batch needs to wait 30 sec before exiting for a user input that can only be a 2-digit number 0 to 30. I found interesting code here, but it doesn't work as expected in Win 10 Cmd. Any ideas why, and how to make it work? If no way, what simple code would you suggest for that task?

Code: Select all

@echo off
    choice /n/c'01234 Input a 2 digit number in range of 00 and 49:
    for %%v in (cls set) do %%v v=0
    for %%v in (1 2 3 4) do if errorlevel }%%v set v=%%v
    choice /n/c'0123456789 %v%
    for %%v in (0 1 2 3 4 5 6 7 8 9) do if errorlevel }%%v set v=%v%%%v
    for %%v in (echo echo.%v% echo pause cls) do %%v.

ShadowThief
Expert
Posts: 1166
Joined: 06 Sep 2013 21:28
Location: Virginia, United States

Re: Waiting a fixed time for restricted user input

#2 Post by ShadowThief » 19 Feb 2016 17:13

That code is not valid in any version of Windows.

It looks like somebody mashed the keyboard until they got something that vaguely resembled batch.
EDIT: I'm fairly certain this is actual MS-DOS batch!

Use the /t option of choice to set a timeout for user input.

sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Re: Waiting a fixed time for restricted user input

#3 Post by sambul35 » 19 Feb 2016 18:45

But how do I derive a 2-digit number entered with choice command - any compact code example?

Aacini
Expert
Posts: 1921
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Waiting a fixed time for restricted user input

#4 Post by Aacini » 19 Feb 2016 19:30

Code: Select all

@echo off
setlocal EnableDelayedExpansion

rem Get a two-digits number from 00 to 29 in 30 seconds,
rem otherwise, "Timed out" is returned

set "digits= 0123456789"

rem Get first digit 0-2 in 30 seconds
set "number=Timed out"
set /P "=Enter a *two-digits* number from 00 to 29: " < NUL
choice /C 012Z /N /T 30 /D Z > NUL
if errorlevel 4 goto end
set "digit=!digits:~%errorlevel%,1!"
set /P "=%digit%" < NUL
set "number=%digit%"

rem Get second digit 0-9 in 15 seconds
choice /C %digits%Z /N /T 15 /D Z > NUL
if errorlevel 11 (
   set "number=Timed out"
) else (
   set "digit=!digits:~%errorlevel%,1!"
   set /P "=!digit!" < NUL
   set "number=%number%!digit!"
)

:end
echo/
echo Number read: %number%

Antonio

sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Re: Waiting a fixed time for restricted user input

#5 Post by sambul35 » 20 Feb 2016 22:54

@Aacini

Thanks for the code sample. :)

sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Re: Waiting a fixed time for restricted user input

#6 Post by sambul35 » 22 Feb 2016 15:14

How these expressions work?

Code: Select all

set /P "=%digit%" < NUL

I can't find on the web a SET /P syntax without variable name. Also redirection < nul is not explained anywhere I looked. :wink:

Code: Select all

digit=!digits:~%errorlevel%,1!

Does that select a digit from the digits array matching errorlevel value?

-----------------------

Also a related example of an enclosed choice expression:

Code: Select all

setlocal EnableDelayedExpansion
:input
choice /c abcdz /m "Enter a letter" /t 10 /d z
if errorlevel 5 (
   choice /c yn /m "Exit the program?" /t 5 /d y
   if !errorlevel! equ 1 (goto :end) else goto :input
)
:end

ShadowThief
Expert
Posts: 1166
Joined: 06 Sep 2013 21:28
Location: Virginia, United States

Re: Waiting a fixed time for restricted user input

#7 Post by ShadowThief » 23 Feb 2016 05:53

sambul35 wrote:How these expressions work?

Code: Select all

set /P "=%digit%" < NUL

I can't find on the web a SET /P syntax without variable name. Also redirection < nul is not explained anywhere I looked. :wink:

Using a variable in a set /p statement is totally optional; it's just that the vast majority of the time, you want to set user input to something. In this case, you have the option of setting it to a variable that you'll never use, but there's no point.

< is the input redirection operator. When combined with a set /p command, this will set the variable to the first line of the file. For example, set /p first_line=<file.txt will set the variable %first_line% to the first line of file.txt.

nul is a non-existent file (it's the same thing as /dev/null if you're familiar with Linux). Since the first line of nothing is nothing, <nul passes nothing to the set /p command, so a variable would also be set to nothing, except we're not using a variable here, so all the code does is display the prompt string without taking input from the user.

This code is used to display text without ending the string in a newline character like echo does.

sambul35 wrote:

Code: Select all

digit=!digits:~%errorlevel%,1!

Does that select a digit from the digits array matching errorlevel value?

Yes, it returns the %errorlevel%th digit in the array (with the first digit being at position 0).

sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Re: Waiting a fixed time for restricted user input

#8 Post by sambul35 » 23 Feb 2016 18:09

Wanted to reference another non-trivial useful code snippet (http://stackoverflow.com/questions/7701 ... with-set-p) offered by Aacini to analyze and timeout user SET /P input with a small file in Assembler catching user keystrokes.

Its amazing what kind of inventiveness MS Cmd developers are expecting from small batch coders, in many cases without merit or need to keep key functions like user input capture and validation so truncated, despite DOS hardware limitations are long gone, while batches remain the most accessible way to keep things automated in Windows without endless click-click. :wink:

sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Re: Waiting a fixed time for restricted user input

#9 Post by sambul35 » 27 Feb 2016 19:24

I need to get some user input in a Win10 64-bit batch with SET /P command, where the input may include undefined number of arbitrary numbers and/or strings separated by space. If no input within 30 sec, print a Choice YN message (return to input or exit).

Is there a workaround to set wait time for user input in this case without using 3rd party programs? May be calling Powershell from the batch may help? If not, what external programs would you suggest suitable for running from a batch?
Last edited by sambul35 on 28 Feb 2016 00:30, edited 1 time in total.

ShadowThief
Expert
Posts: 1166
Joined: 06 Sep 2013 21:28
Location: Virginia, United States

Re: Waiting a fixed time for restricted user input

#10 Post by ShadowThief » 27 Feb 2016 23:22

sambul35 wrote:Wanted to reference another non-trivial useful code snippet (http://stackoverflow.com/questions/7701 ... with-set-p) offered by Aacini to analyze and timeout user SET /P input with a small file in Assembler catching user keystrokes.

Its amazing what kind of inventiveness MS Cmd developers are expecting from small batch coders, in many cases without merit or need to keep key functions like user input capture and validation so truncated, despite DOS hardware limitations are long gone, while batches remain the most accessible way to keep things automated in Windows without endless click-click. :wink:

DEBUG is a 16-bit program, so it won't work on 64-bit operating systems, sadly.

ShadowThief
Expert
Posts: 1166
Joined: 06 Sep 2013 21:28
Location: Virginia, United States

Re: Waiting a fixed time for restricted user input

#11 Post by ShadowThief » 27 Feb 2016 23:22

sambul35 wrote:Wanted to reference another non-trivial useful code snippet (http://stackoverflow.com/questions/7701 ... with-set-p) offered by Aacini to analyze and timeout user SET /P input with a small file in Assembler catching user keystrokes.

Its amazing what kind of inventiveness MS Cmd developers are expecting from small batch coders, in many cases without merit or need to keep key functions like user input capture and validation so truncated, despite DOS hardware limitations are long gone, while batches remain the most accessible way to keep things automated in Windows without endless click-click. :wink:

DEBUG is a 16-bit program, so it won't work on 64-bit operating systems, sadly.

Aacini
Expert
Posts: 1921
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Waiting a fixed time for restricted user input

#12 Post by Aacini » 28 Feb 2016 01:06

I take the pure Batch file solution posted at this site and slightly modified it for this request. It works pretty well:

Code: Select all

@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

:Input
del InputLine.txt 2> NUL
set "input="
(
   set /P "input=You have 30 seconds to complete the input: " > CON
   > InputLine.txt call set /P "=%%input%%" < NUL
) 2> NUL | "%~F0" TimeoutMonitor 30
set /P "input=" < InputLine.txt
del InputLine.txt
if "%input%" neq "Timed Out" goto inputOK
choice /N /M "Timed out, return to input? "
if %errorlevel% equ 1 goto Input
goto :EOF

:inputOK
echo Input read: "%input%"
goto :EOF


:TimeoutMonitor seconds

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
)

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

Antonio

einstein1969
Expert
Posts: 961
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Waiting a fixed time for restricted user input

#13 Post by einstein1969 » 28 Feb 2016 04:43

Hi Antonio,

This is good piece of code!

In the last I think that is better use:

Code: Select all

rem Timed out: kill the SET /P process and create a standard input line
echo/
echo Timed Out> InputLine.txt
taskkill /PID %leftSidePipePID% /F > NUL


than:

Code: Select all

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


In the first case i think is necessary a LOCK for a inputLine.txt

Than I have tested the original version in a complex scenario. If you execute varius times and adding execute othe cmd.exe in the middle , some of input timeout NOT WORK. I think that the tasklist is not the good choice. Are you shure that the list of task is always in that order?


Einstein1969

sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Re: Waiting a fixed time for restricted user input

#14 Post by sambul35 » 28 Feb 2016 14:42

@Aacini

Thanks again for the code sample. :D

I also wanted to share some more restricted user input processing with set /p in a hope someone would find it handy for their project:

Code: Select all

@echo off
rem Enter any number(s) within 5 sec each from a known array without repeating
setlocal EnableDelayedExpansion
set "num=1 8 3 7 5 6 4 2 9" & set "lst=!num: =!" & set "count=1"
for %%i in (%num%) do set /a count+=1
echo/ & set /p "=Enter any number(s) from the pull: %num% (wait to exit) > "<nul

:input
choice /c %lst%Z /N /t 5 /d Z > nul
if errorlevel %count% (
   if not defined digit (
      (echo/ & echo/) & choice /C YN /M "Exit the program?" /T 5 /D Y
      if !errorlevel! equ 1 (goto :end) else (echo/ & goto :input)
      )
   goto :cont
)
rem // repeat numbers input on the same line, filter out duplicates
set /a "pos=%errorlevel%-1"
set "digit=!lst:~%pos%,1!"
for %%k in (!cams!) do if %%k equ !digit! goto :input
set "cams=!cams! !digit!"
set /P "=!digit! "<nul
set num=!num:~2!
if not !num!=="" goto :input

:cont
echo/ & echo/ & echo Entered numbers !cams!

:end
echo/ & echo Bye...


Entering 0 2 2 1 0 7 1 3 3 m n 3 3 3 7 3 k 3 1 1 1 1 will produce:

Code: Select all

Entered numbers 2 1 7 3
Last edited by sambul35 on 29 Feb 2016 16:32, edited 11 times in total.

sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Re: Waiting a fixed time for restricted user input

#15 Post by sambul35 » 29 Feb 2016 15:50

Is there a way to enter any number(s) within 5 sec each from a 20 random 1 and 2 digit number array on the same line in a short(er) code?

How to add a "caret return" (Enter) in choice /c parameters list?

Post Reply