I know that by using the "timeout" command, I can wait for specified amount of time; but my question is that what if this would be an automatic operation that could be prevented by user? I mean suppose that I wanted to do the operation A but by using the "timeout" command I wait if user wants to cancel this operation or not; for example during this waiting process if user pressed the Enter key then batch script execute something else(not operation A);
6 Answers
timeout is just to induce a delay before an action, not to let the user choose something. I f you still want to use it, you need to ask the user to press Control-C to break before the timeout command, and catch the ERRORLEVEL after that.
Else choice is your friend here:
C:\Users\mm>CHOICE /T 10 /C yYcC /CS /D y /M "Press y to validate, c to Cancel. You have 10 sec delay [Default y]:"
Press y to validate, c to Cancel. You have 10 sec delay [Default y]: [y,Y,c,C]?y
And you can test returned value with ERRORLEVEL. Here, I pressed nothing, so y get selected (default value via /D) and ERRORLEVEL is 1 (1st option). The countdown is not displayed though.
1 Comment
As indicated by Aacini, no, timeout has been built without this feature.
This can be used as a workaround
@echo off
call :controlTimeout 5
if errorlevel 1 (
echo timeout was cancelled
) else (
echo timeout reached
)
exit /b
:controlTimeout
setlocal
start "" /belownormal /b cmd /q /d /c "timeout.exe %~1 /nobreak > nul"
timeout.exe %~1 & tasklist | find "timeout" >nul
if errorlevel 1 ( set "exitCode=0" ) else (
set "exitCode=1"
taskkill /f /im timeout.exe 2>nul >nul
)
endlocal & exit /b %exitCode%
This just starts two instances of timeout, one in background that is only cancelable with Ctrl+C and one in the active console. When the timeout command in console finished, tasklist is used to determine if the background timeout task is still active. If it is, then the visible timeout has been canceled, else timeout has been reached.
Comments
Wow! I always thought that this capability was inherent to timeout, but it is not! There is no way to know if timeout command ends because the time out or because a key press...
However, it is possible to know if the time out was cancelled by Ctrl-C, instead by a normal key! In this case, the errorlevel value returned by timeout is different than zero:
C:\> timeout 60
Waiting for 47^Ceconds, press a key to continue ...
C:\> echo %errorlevel%
-1073741510
However, if you use this command inside a Batch file, the Ctrl-C press also cancel its execution! So the answer is: NO, there is no way to detect this point... :-(
Comments
Based on the discussion with @jeb on @pologug's answer I finally came up with the following one-liner:
timeout -t 4 |findstr "\<0\>" >nul && echo timedOut || echo cancelled
Timeout uses control characters to relocate the cursor to the remaining seconds to rewrite them. Polo's and Jeb's answers employ a for loop to capture the seconds. This captured string contains the control characters and the string has to be postprocessed to be useful.
My answer uses findstr to search for 0 by word boundaries (making sure 10 or 204 aren't found). Thankfully, findstr treats control characters as "non-word-characters"
Instead of echo you can simply use goto to jump to different parts of the code.
Same downside as Jeb's answer though: the timeout-prompt isn't displayed (due to the piping).
Comments
@echo off & setlocal
set cnt=4
for /f tokens^=3^ delims^=^. %%i in ('timeout -t %cnt%^|find "."') do (
echo %%i
)
pause
8 Comments
:DBased on the answer from @polo gug:
@echo off
set cnt=9
for /F "tokens=1,2 delims=# " %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
set "BS=%%a"
)
for /f "tokens=*" %%1 in ('timeout -t %cnt%') do (
set "line=%%1"
)
set remain=%line:~-2%
if "%remain%" == " 0" goto :timeout %= This is true for timeouts longer than 9 seconds =%
if "%remain%" == "%BS%0" goto :timeout %= This is true for timeouts shorter than 10 secondes
echo Canceled by user
exit /b
:timeout
echo Timeout occured
It grabs the output from the timeout command, then it inspects the last two characters.
If the remaining string is <space>0 or <backspace>0 then a timeout occured, else the user has canceled the timeout before.
Only test the last character against 0 isn't enough, because the remaining text could be ex. 20.
1 Comment
for loop doesn't even need the loop anymore.
CHOICEcommand help (there's even better option withXCOPYbut will take me time to create a script)choiceyou have a timeout...