How to wait in a batch script? [duplicate] - batch-file

When writing a batch file to automate something on a Windows box, I've needed to pause its execution for several seconds (usually in a test/wait loop, waiting for a process to start). At the time, the best solution I could find uses ping (I kid you not) to achieve the desired effect. I've found a better write-up of it here, which describes a callable "wait.bat", implemented as follows:
#ping 127.0.0.1 -n 2 -w 1000 > nul
#ping 127.0.0.1 -n %1% -w 1000> nul
You can then include calls to wait.bat in your own batch file, passing in the number of seconds to sleep.
Apparently the Windows 2003 Resource Kit provides a Unix-like sleep command (at last!). In the meantime, for those of us still using Windows XP, Windows 2000 or (sadly) Windows NT, is there a better way?
I modified the sleep.py script in the accepted answer, so that it defaults to one second if no arguments are passed on the command line:
import time, sys
time.sleep(float(sys.argv[1]) if len(sys.argv) > 1 else 1)

The timeout command is available from Windows Vista onwards:
c:\> timeout /?
TIMEOUT [/T] timeout [/NOBREAK]
Description:
This utility accepts a timeout parameter to wait for the specified
time period (in seconds) or until any key is pressed. It also
accepts a parameter to ignore the key press.
Parameter List:
/T timeout Specifies the number of seconds to wait.
Valid range is -1 to 99999 seconds.
/NOBREAK Ignore key presses and wait specified time.
/? Displays this help message.
NOTE: A timeout value of -1 means to wait indefinitely for a key press.
Examples:
TIMEOUT /?
TIMEOUT /T 10
TIMEOUT /T 300 /NOBREAK
TIMEOUT /T -1
Note: It does not work with input redirection - trivial example:
C:\>echo 1 | timeout /t 1 /nobreak
ERROR: Input redirection is not supported, exiting the process immediately.

Using the ping method as outlined is how I do it when I can't (or don't want to) add more executables or install any other software.
You should be pinging something that isn't there, and using the -w flag so that it fails after that amount of time, not pinging something that is there (like localhost) -n times. This allows you to handle time less than a second, and I think it's slightly more accurate.
e.g.
(test that 1.1.1.1 isn't taken)
ECHO Waiting 15 seconds
PING 1.1.1.1 -n 1 -w 15000 > NUL
or
PING -n 15 -w 1000 127.1 >NUL

UPDATE
The timeout command, available from Windows Vista and onwards should be the command used, as described in another answer to this question. What follows here is an old answer.
Old answer
If you have Python installed, or don't mind installing it (it has other uses too :), just create the following sleep.py script and add it somewhere in your PATH:
import time, sys
time.sleep(float(sys.argv[1]))
It will allow sub-second pauses (for example, 1.5 sec, 0.1, etc.), should you have such a need. If you want to call it as sleep rather than sleep.py, then you can add the .PY extension to your PATHEXT environment variable. On Windows XP, you can edit it in:
My Computer → Properties (menu) → Advanced (tab) → Environment Variables (button) → System variables (frame)

SLEEP.exe is included in most Resource Kits e.g. The Windows Server 2003 Resource Kit which can be installed on Windows XP too.
Usage: sleep time-to-sleep-in-seconds
sleep [-m] time-to-sleep-in-milliseconds
sleep [-c] commited-memory ratio (1%-100%)

I disagree with the answers I found here.
I use the following method entirely based on Windows XP capabilities to do a delay in a batch file:
DELAY.BAT:
#ECHO OFF
REM DELAY seconds
REM GET ENDING SECOND
FOR /F "TOKENS=1-3 DELIMS=:." %%A IN ("%TIME%") DO SET /A H=%%A, M=1%%B%%100, S=1%%C%%100, ENDING=(H*60+M)*60+S+%1
REM WAIT FOR SUCH A SECOND
:WAIT
FOR /F "TOKENS=1-3 DELIMS=:." %%A IN ("%TIME%") DO SET /A H=%%A, M=1%%B%%100, S=1%%C%%100, CURRENT=(H*60+M)*60+S
IF %CURRENT% LSS %ENDING% GOTO WAIT
You may also insert the day in the calculation so the method also works when the delay interval pass over midnight.

I faced a similar problem, but I just knocked up a very short C++ console application to do the same thing. Just run MySleep.exe 1000 - perhaps easier than downloading/installing the whole resource kit.
#include <tchar.h>
#include <stdio.h>
#include "Windows.h"
int _tmain(int argc, _TCHAR* argv[])
{
if (argc == 2)
{
_tprintf(_T("Sleeping for %s ms\n"), argv[1]);
Sleep(_tstoi(argv[1]));
}
else
{
_tprintf(_T("Wrong number of arguments.\n"));
}
return 0;
}

You can use ping:
ping 127.0.0.1 -n 11 -w 1000 >nul: 2>nul:
It will wait 10 seconds.
The reason you have to use 11 is because the first ping goes out immediately, not after one second. The number should always be one more than the number of seconds you want to wait.
Keep in mind that the purpose of the -w is not to control how often packets are sent, it's to ensure that you wait no more than some time in the event that there are network problems. There are unlikely to be problems if you're pinging 127.0.0.1 so this is probably moot.
The ping command on its own will normally send one packet per second. This is not actually documented in the Windows docs but it appears to follow the same rules as the Linux version (where it is documented).

Over at Server Fault, a similar question was asked, and the solution there was:
choice /d y /t 5 > nul

You could use the Windows cscript WSH layer and this wait.js JavaScript file:
if (WScript.Arguments.Count() == 1)
WScript.Sleep(WScript.Arguments(0)*1000);
else
WScript.Echo("Usage: cscript wait.js seconds");

Depending on your compatibility needs, either use ping:
ping -n <numberofseconds+1> localhost >nul 2>&1
e.g. to wait 5 seconds, use
ping -n 6 localhost >nul 2>&1
or on Windows 7 or later use timeout:
timeout 6 >nul

There is a better way to sleep using ping. You'll want to ping an address that does not exist, so you can specify a timeout with millisecond precision. Luckily, such an address is defined in a standard (RFC 3330), and it is 192.0.2.x. This is not made-up, it really is an address with the sole purpose of not-existing. To be clear, this applies even in local networks.
192.0.2.0/24 - This block is assigned as "TEST-NET" for use in
documentation and example code. It is often used in conjunction with
domain names example.com or example.net in vendor and protocol
documentation. Addresses within this block should not appear on the
public Internet.
To sleep for 123 milliseconds, use ping 192.0.2.1 -n 1 -w 123 >nul
Update: As per the comments, there is also 127.255.255.255.

If you've got PowerShell on your system, you can just execute this command:
powershell -command "Start-Sleep -s 1"
Edit: from my answer on a similar thread, people raised an issue where the amount of time powershell takes to start is significant compared to how long you're trying to wait for. If the accuracy of the wait time is important (ie a second or two extra delay is not acceptable), you can use this approach:
powershell -command "$sleepUntil = [DateTime]::Parse('%date% %time%').AddSeconds(5); $sleepDuration = $sleepUntil.Subtract((get-date)).TotalMilliseconds; start-sleep -m $sleepDuration"
This takes the time when the windows command was issued, and the powershell script sleeps until 5 seconds after that time. So as long as powershell takes less time to start than your sleep duration, this approach will work (it's around 600ms on my machine).

timeout /t <seconds> <options>
For example, to make the script perform a non-uninterruptible 2-second wait:
timeout /t 2 /nobreak >NUL
Which means the script will wait 2 seconds before continuing.
By default, a keystroke will interrupt the timeout, so use the /nobreak switch if you don't want the user to be able to interrupt (cancel) the wait. Furthermore, the timeout will provide per-second notifications to notify the user how long is left to wait; this can be removed by piping the command to NUL.
edit: As #martineau points out in the comments, the timeout command is only available on Windows 7 and above. Furthermore, the ping command uses less processor time than timeout. I still believe in using timeout where possible, though, as it is more readable than the ping 'hack'. Read more here.

Just put this in your batch file where you want the wait.
#ping 127.0.0.1 -n 11 -w 1000 > null

In Notepad, write:
#echo off
set /a WAITTIME=%1+1
PING 127.0.0.1 -n %WAITTIME% > nul
goto:eof
Now save as wait.bat in the folder C:\WINDOWS\System32,
then whenever you want to wait, use:
CALL WAIT.bat <whole number of seconds without quotes>

The Resource Kit has always included this. At least since Windows 2000.
Also, the Cygwin package has a sleep - plop that into your PATH and include the cygwin.dll (or whatever it's called) and way to go!

The usage of ping is good, as long as you just want to "wait for a bit". This since you are dependent on other functions underneath, like your network working and the fact that there is nothing answering on 127.0.0.1. ;-) Maybe it is not very likely it fails, but it is not impossible...
If you want to be sure that you are waiting exactly the specified time, you should use the sleep functionality (which also have the advantage that it doesn't use CPU power or wait for a network to become ready).
To find an already made executable for sleep is the most convenient way. Just drop it into your Windows folder or any other part of your standard path and it is always available.
Otherwise, if you have a compiling environment you can easily make one yourself.
The Sleep function is available in kernel32.dll, so you just need to use that one. :-)
For VB / VBA declare the following in the beginning of your source to declare a sleep function:
private Declare Sub Sleep Lib "kernel32" Alias "Sleep" (byval dwMilliseconds as Long)
For C#:
[DllImport("kernel32.dll")]
static extern void Sleep(uint dwMilliseconds);
You'll find here more about this functionality (available since Windows 2000) in Sleep function (MSDN).
In standard C, sleep() is included in the standard library and in Microsoft's Visual Studio C the function is named Sleep(), if memory serves me. ;-) Those two takes the argument in seconds, not in milliseconds as the two previous declarations.

I like Aacini's response. I added to it to handle the day and also enable it to handle centiseconds (%TIME% outputs H:MM:SS.CC):
:delay
SET DELAYINPUT=%1
SET /A DAYS=DELAYINPUT/8640000
SET /A DELAYINPUT=DELAYINPUT-(DAYS*864000)
::Get ending centisecond (10 milliseconds)
FOR /F "tokens=1-4 delims=:." %%A IN ("%TIME%") DO SET /A H=%%A, M=1%%B%%100, S=1%%C%%100, X=1%%D%%100, ENDING=((H*60+M)*60+S)*100+X+DELAYINPUT
SET /A DAYS=DAYS+ENDING/8640000
SET /A ENDING=ENDING-(DAYS*864000)
::Wait for such a centisecond
:delay_wait
FOR /F "tokens=1-4 delims=:." %%A IN ("%TIME%") DO SET /A H=%%A, M=1%%B%%100, S=1%%C%%100, X=1%%D%%100, CURRENT=((H*60+M)*60+S)*100+X
IF DEFINED LASTCURRENT IF %CURRENT% LSS %LASTCURRENT% SET /A DAYS=DAYS-1
SET LASTCURRENT=%CURRENT%
IF %CURRENT% LSS %ENDING% GOTO delay_wait
IF %DAYS% GTR 0 GOTO delay_wait
GOTO :EOF

I have been using this C# sleep program. It might be more convenient for you if C# is your preferred language:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace sleep
{
class Program
{
static void Main(string[] args)
{
if (args.Length == 1)
{
double time = Double.Parse(args[0]);
Thread.Sleep((int)(time*1000));
}
else
{
Console.WriteLine("Usage: sleep <seconds>\nExample: sleep 10");
}
}
}
}

Even more lightweight than the Python solution is a Perl
one-liner.
To sleep for seven seconds put this in the BAT script:
perl -e "sleep 7"
This solution only provides a resolution of one second.
If you need higher resolution then use the Time::HiRes
module from CPAN. It provides usleep() which sleeps in
microseconds and nanosleep() which sleeps in nanoseconds
(both functions takes only integer arguments). See the
Stack Overflow question How do I sleep for a millisecond in Perl? for further details.
I have used ActivePerl for many years. It is very easy to
install.

Or command line Python, for example, for 6 and a half seconds:
python -c "import time;time.sleep(6.5)"

The best solution that should work on all Windows versions after Windows 2000 would be:
timeout numbersofseconds /nobreak > nul

There are lots of ways to accomplish a 'sleep' in cmd/batch:
My favourite one:
TIMEOUT /NOBREAK 5 >NUL 2>NUL
This will stop the console for 5 seconds, without any output.
Most used:
ping localhost -n 5 >NUL 2>NUL
This will try to make a connection to localhost 5 times. Since it is hosted on your computer, it will always reach the host, so every second it will try the new every second. The -n flag indicates how many times the script will try the connection. In this case is 5, so it will last 5 seconds.
Variants of the last one:
ping 1.1.1.1 -n 5 >nul
In this script there are some differences comparing it with the last one. This will not try to call localhost. Instead, it will try to connect to 1.1.1.1, a very fast website. The action will last 5 seconds only if you have an active internet connection. Else it will last approximately 15 to complete the action. I do not recommend using this method.
ping 127.0.0.1 -n 5 >nul
This is exactly the same as example 2 (most used). Also, you can also use:
ping [::1] -n 5 >nul
This instead, uses IPv6's localhost version.
There are lots of methods to perform this action. However, I prefer method 1 for Windows Vista and later versions and the most used method (method 2) for earlier versions of the OS.

The pathping.exe can sleep less than second.
#echo off
setlocal EnableDelayedExpansion
echo !TIME! & pathping localhost -n -q 1 -p %~1 2>&1 > nul & echo !TIME!
.
> sleep 10
17:01:33,57
17:01:33,60
> sleep 20
17:03:56,54
17:03:56,58
> sleep 50
17:04:30,80
17:04:30,87
> sleep 100
17:07:06,12
17:07:06,25
> sleep 200
17:07:08,42
17:07:08,64
> sleep 500
17:07:11,05
17:07:11,57
> sleep 800
17:07:18,98
17:07:19,81
> sleep 1000
17:07:22,61
17:07:23,62
> sleep 1500
17:07:27,55
17:07:29,06

I am impressed with this one:
http://www.computerhope.com/batch.htm#02
choice /n /c y /d y /t 5 > NUL
Technically, you're telling the choice command to accept only y. It defaults to y, to do so in 5 seconds, to draw no prompt, and to dump anything it does say to NUL (like null terminal on Linux).

You can also use a .vbs file to do specific timeouts:
The code below creates the .vbs file. Put this near the top of you rbatch code:
echo WScript.sleep WScript.Arguments(0) >"%cd%\sleeper.vbs"
The code below then opens the .vbs and specifies how long to wait for:
start /WAIT "" "%cd%\sleeper.vbs" "1000"
In the above code, the "1000" is the value of time delay to be sent to the .vbs file in milliseconds, for example, 1000 ms = 1 s. You can alter this part to be however long you want.
The code below deletes the .vbs file after you are done with it. Put this at the end of your batch file:
del /f /q "%cd%\sleeper.vbs"
And here is the code all together so it's easy to copy:
echo WScript.sleep WScript.Arguments(0) >"%cd%\sleeper.vbs"
start /WAIT "" "%cd%\sleeper.vbs" "1000"
del /f /q "%cd%\sleeper.vbs"

Just for fun, if you have Node.js installed, you can use
node -e 'setTimeout(a => a, 5000)'
to sleep for 5 seconds. It works on a Mac with Node v12.14.0.

You can get fancy by putting the PAUSE message in the title bar:
#ECHO off
SET TITLETEXT=Sleep
TITLE %TITLETEXT%
CALL :sleep 5
GOTO :END
:: Function Section
:sleep ARG
ECHO Pausing...
FOR /l %%a in (%~1,-1,1) DO (TITLE Script %TITLETEXT% -- time left^
%%as&PING.exe -n 2 -w 1000 127.1>NUL)
EXIT /B 0
:: End of script
:END
pause
::this is EOF

This was tested on Windows XP SP3 and Windows 7 and uses CScript. I put in some safe guards to avoid del "" prompting. (/q would be dangerous)
Wait one second:
sleepOrDelayExecution 1000
Wait 500 ms and then run stuff after:
sleepOrDelayExecution 500 dir \ /s
sleepOrDelayExecution.bat:
#echo off
if "%1" == "" goto end
if NOT %1 GTR 0 goto end
setlocal
set sleepfn="%temp%\sleep%random%.vbs"
echo WScript.Sleep(%1) >%sleepfn%
if NOT %sleepfn% == "" if NOT EXIST %sleepfn% goto end
cscript %sleepfn% >nul
if NOT %sleepfn% == "" if EXIST %sleepfn% del %sleepfn%
for /f "usebackq tokens=1*" %%i in (`echo %*`) DO # set params=%%j
%params%
:end

Since others are suggesting 3rd party programs (Python, Perl, custom app, etc), another option is GNU CoreUtils for Windows available at http://gnuwin32.sourceforge.net/packages/coreutils.htm.
2 options for deployment:
Install full package (which will include the full suite of CoreUtils, dependencies, documentation, etc).
Install only the 'sleep.exe' binary and necessary dependencies (use depends.exe to get dependencies).
One benefit of deploying CoreUtils is that you'll additionally get a host of other programs that are helpful for scripting (Windows batch leaves a lot to be desired).

Related

timeout /t 10 /nobreak > NUL is getting stuck and not coming out to execute next statement on windows 2003 server VM

"timeout /t 10 /nobreak > NUL" is getting stuck and not coming out to execute the next statement.
I have written a below script which executes as expected on my dev machine and also tested on few test machines also. it waits for 10 seconds and the again start execution (tested in safe mode also), but on one of the machine windows 2003 server which license is expired my script runs in safe mode, but when executing the above timeout statement it doesn't execute the next statement.
Can someone please tell me the reason if any and what will be the solution?
set restart=1
...
... some other code
...
setlocal ENABLEDELAYEDEXPANSION
:WaitToRestart
if "%restart%"=="1" (
echo waiting for restart >> log.txt
shutdown /r /t 0
if "!errorlevel!" NEQ "0" (
echo error: !errorlevel! while restarting so wait for 10 sec >> log.txt
timeout /t 10 /nobreak > NUL
goto WaitToRestart
)
echo error: !errorlevel! you shuld not be here to see after death >> log.txt
)
setlocal DisableDelayedExpansion
On my dev machine, this script runs well (windows 10) but stuck on the production environment (where it runs as a startup script which run after boot in safe mode) on Windows 2003.
So I change the "timeout" command with command "PING localhost -n 6 >NUL" but it also stuck after rotating 10, 12 times. And when I removed "PING" command also then it rotates for a long time till the command "shutdown" executed successfully.
It looks like the machine-specific issue and maybe stopped because of license expire issue as the I have created VM from backup of physical machine
If you're just trying to get a wait function, you can manipulate ping to do that.
ping 0 -w 1000 -n 10 >nul
Breaking this apart piece by piece, cmd expands 0 to 0.0.0.0, which is the IP address cmd will try to ping (it doesn't exist). -w specifies the number of milliseconds ping will wait before timing out a request. -n specifies how many requests you'd like to send (so your total duration, in seconds is w/1000 * n). >nul is not ping-specific; it nullifies the output to the console.
By pinging an IP that doesn't exist, you force ping to timeout with every request, which gets you a dependable wait time.

Need batch for Netstat -anbo to run ever 30 minutes

Title description as stated. I'm very novice at this, so please go easy. I've searched articles here, and have tried several iterations of how to do this but my attempts have failed.
I need to run Netstat -anbo every 30 minutes to a text file and keep them rolling for at least 5 files.
Thanks.
Here's how you can run something every few secs in batch script, without the 'sleep' utility.. I will leave the implementation up to you :)
# :loop
REM "do something every 10 secs"
# ping localhost -n 11 > nul
# goto loop
The ping acts as a sleep here.. you can even ping to any non-existent host.
If you want a more accurate time interval, you are better off using
# :loop
REM Execute the MS-DOS dir command ever 20 seconds.
# SLEEP 20
# GOTO loop
For this to work, you will need to have a sleep MS-DOS utility on the computer. You can find it here
You would have to use a simple loop and timeout
A sample implementation
#echo off
:loop
netstat -anbo >> file.txt # >> Will append to file instead of erasing file content
timeout /t 1800 /nobreak # /t timeout in seconds /nobreak Ignore key presses and wait for specified time
goto :loop #Simple loop to keep batch running indefinitely
Remember to run this batch as administrator (For netstat)

Glitch when running homemade script CMD

I have been dinking around with batch files, and decided to have a little bit of fun creating a command usable in the command line "Hack", which looks like it will make it look like something bad is happening, but nothing really is. Here is the source for that:
#echo off
ECHO Parsing Buffer Strings...
Delay 3000
ECHO Reading Args from FTP Protocol...
Delay 3000
ECHO Interpreting BAUD rate...
Delay 3000
ECHO Reading IBM Standards...
Delay 3000
ECHO Removing Multiplexer matrices...
Delay 3000
ECHO Compiling zip files...
Delay 3000
ECHO Complete. System OS bypassed.
PAUSE
Now, as you may have noticed, there is no built-in "Delay" command, so I made one myself, placing the newly made Batch file in System32 along with Hack.bat:
#echo off
ping 1.1.1.1 -n 1 -w %1 > nul
This takes in one parameter, the amount of delay (ms), and pings a non-existent computer. It tries once to ping it, waiting %1 ms before it gives up. Now, when I put it the command "Hack", it says "Parsing buffer strings", waits three seconds, then the script stops. Now, when I turned echo on to see what the problem was, it said "Parsing buffer strings\nDelay 3000", waited three seconds, then the script stopped. Why? Thank you.
where is your procedure definition and it's call ? you shoud have done someting like :
echo parsing ...
call :delay 3000
echo reading ...
call :delay 3000
exit
:delay
ping 1.1.1.1 -n 1 -w %1 > nul
ping addr -n 1 -w 3000 will only work as long as addr is unreachable. When for some reason the address becomes reachable, the command will return immediately. It will also pollute the network (just a little, but still).
If you don't need millisecond delays, a better approach would be something like this:
#echo off
echo %TIME%
call :delay 5
echo %TIME%
goto :eof
:delay
set /a count=%1+1
ping -n %count% 127.0.0.1 >nul
Output:
C:\>delay.cmd
12:47:44,33
12:47:49,38
ping has a delay of roughly 1 second between two echo requests, so you can sleep for n seconds by sending n+1 echo requests to localhost.

Pause a batch file until a host is reachable (using ping)?

I'm looking to add some functionality to a batch file that I've been writing;
essentially what happens is I dial up a VPN connection using openvpn and then continue to mount a network drive as well as many other things, what I'm looking to do is:
Dial the connection via OpenVPN (which I have working fine)
Ping a host on the other side of the VPN and don't continue through the batch file until this host is reachable.
Currently I've been using a sleep command of 20 seconds which works, but is not a very clean or intelligent way of going about it; I'd imagine I need some sort of loop to attempt to ping the host infinitely until it is reachable before continuing in the batch file. Any help would be greatly appreciated.
from antoher thread on stackoverflow... credit to paxdiablo (find the original post here)
#setlocal enableextensions enabledelayedexpansion
#echo off
set ipaddr=%1
:loop
set state=down
for /f "tokens=5,7" %%a in ('ping -n 1 !ipaddr!') do (
if "x%%a"=="xReceived" if "x%%b"=="x1," set state=up
)
echo.Link is !state!
ping -n 6 127.0.0.1 >nul: 2>nul:
goto :loop
endlocal
This will give you enough ammo to use and solve your problem
as already mentioned years ago, output of ping is language dependent, so it's not a good idea to rely on a string like Received. The preferred and most reliable method is searching for the string TTL=:
:loop
timeout 2
ping -n 1 %ipaddress% |find "TTL=" || goto :loop
echo Answer received.
|| works as "if previous command (find) wasn't successful, then"
(as for the timeout: never build a loop without some idle time to reduce CPU load)
It works if You translate the "Received" string using the string that your language uses for the word Received (i.e. in Italian is Ricevuti).

Run DOS Command for a Time Limit

I want to perform the following operations.
Read 1 word at a time from an input file consisting of many words.
Pass this word as an argument to another command line based application.
Run that application for a fixed amount of time, say 10 seconds.
Abort the execution of the application if it is still running after 10 seconds and go back, pick the next word from the input file and repeat steps 1 to 3.
Here is what I have written though it does not achieve exactly what I want it to:
#echo off
for /f %%i in ('type input.txt') do call:Routine %%i
:Routine
set app="myApp.exe"
set limit=60
%app% %1
goto Delay
:Delay
ping localhost -n %limit% > nul
The above script will introduce the delay after the execution of myApp has completed. However, I want it to run myApp.exe for not more than 10 seconds, if it does, then abort the application using taskkill and move on to the next word from the input file.
I searched for a solution online and came across this:
http://www.tech-archive.net/Archive/WinXP/microsoft.public.windowsxp.general/2006-04/msg03609.html
Though it does not answer my query exactly, I would like to make my code do something similar.
Thanks.
The logic in the linked code looks flawed: It either launches 3 download commands, or it delays ~59 seconds and attempts to kill all download commands, but it never does both. The TASKKILL command arguments are not correct - the imagename belongs after the /IM parameter.
In your code, you are not going to kill your task without the TASKKILL command!
You must GOTO :EOF or EXIT /B after your loop finishes, otherwise the code will fall through and execute the subroutine without using CALL. But there really is no need to use a subroutine at all.
You only need to initialize your variables once.
No need to execute a command in your IN() clause. FOR /F has a variation that can read the text file directly. Type HELP FOR from the command line and read the documentation carefully.
PING has roughly a 1 second delay between each echo request. So a count of 11 will yield a delay of roughly 10 seconds.
EDIT - originally forgot the critical START command to start the app in its own process
#echo off
set app="myApp.exe"
set limit=11
for /f %%i in (input.txt) do (
start "" %app% %%i
ping localhost -n %limit% > nul
taskkill /im %app% /f
)

Resources