I'm currently running a set of commands that utilizes the timeout function in my batch files. The timeout function uses a variable for how many seconds it should pause, and I think that may be causing issues, but I desperately need it to function properly.
I've got an update to my question which details more about what may be happening.
I used some suggestions that I had in the comments to try and fix my script, but it did not work.
Here is my script:
:connectToTheInternet
setlocal EnableDelayedExpansion
set timeout=2
echo checking internet connection
echo.
:connectToTheInternetRestart
ping -n 1 google.com | find /i "TTL=" >NUL && (
echo Internet connection already established, checking script versions.
echo.
goto scriptVersion
REM toupd
) || (
if "%COUNTER%"=="0" (
echo Creating wifi profile.
echo.
set /A COUNTER=1
goto createWifiProfile
)
SET /A "tries = (%COUNTER%-1)+1"
REM if failed endonfail times, give up
if "%COUNTER%"=="%endonfail%" (
echo Error: Could not connect to network %tries% times, stopping script.
echo.
goto endNoShutdown
)
echo.
echo Attempt #%COUNTER%.
echo.
REM raise waiting time between connections
SET /A "modulo = (%COUNTER%-1) %% 2"
if "%modulo%" EQU "0" (
set /A timeout=timeout+2
echo failed %tries% times in a row. Increasing wait time between actions to %timeout% seconds.
set /A COUNTER=COUNTER+1
) else (
set /A COUNTER=COUNTER+1
)
REM disconnect existing network
netsh wlan disconnect
netsh wlan delete profile name="%wifissid%"
timeout /t 1 /nobreak
echo.
REM attempt connection
netsh wlan add profile filename="connect.xml"
netsh wlan connect name="%wifissid%" ssid="%wifissid%" >NUL
echo.
echo Wait time is currently !timeout! seconds.
timeout /t !timeout! /nobreak
echo.
REM check pings
ping -n 1 google.com | find /i "TTL=" >NUL && (
echo Successfully connected. Checking script version.
echo.
goto scriptVersion
) || (
set /a COUNTER2=COUNTER+1
echo Connection attempt failed. Starting attempt #%COUNTER2% in 3 seconds.
echo.
timeout /t 3 /nobreak
cls
goto connectToTheInternetRestart
)
)
My problem is specifically the timeout /t !timeout! /nobreak which should wait for a variabled amount of time. The problem is, sometimes (it only happens when the device successfully connects to the internet, but not every time the device connects to the internet) the timeout jumps up to 10,000 seconds, 30,000 seconds or some other random high number (And they really are random, I've seen some at like 12,536 seconds.) When it should always be less than 12 based on the timeout variable. Yes, I mean seconds NOT milliseconds. As you can imagine, there is a big difference between 10k seconds (roughly 21 days) vs 10 seconds.
I have no idea what could be causing this, or how to solve it and would love some help.
Here's a left-field thought, brought about by your comment
(it only happens when the device successfully connects to the internet, but not every time the device connects to the internet)
Before it connects to the internet, is the date, time and timezone correct? Connecting will synchronise the time - which may muck up your timeouts!
Like I said: left-field, but...
choice seems not to be affected by the mentioned behaviour of timeout: "when changing the time from another cmd window while running a timeout 300, the "waiting for ..." prompt indeed changes the remaining time accordingly".
So instead of timeout /t !timeout! you can use
choice /n /c yn /d y /t !timeout!
/c yn is just for making it language independent.
Related
this is my first post here so please excuse me for getting anything wrong.
I have a few computers that run Octane renderer. One is the "Master" and the others are "Slaves". When the Master is unreachable the Slaves can't render so I'd like to save money and the environment by having a small batch script for when this happens.
My thinking to a solution was to have a batch script on the Slaves to ping the Master every 5 mins to check there is a connection. When the ping fails it tries again 3 times and if it fails every time the Slave shuts down.
I've got this script from another post here that I did minor edits to : Batch File to reboot pc on network connectivity loss but it doesn't work for what I need. When I run it with the ping ip set to the Master's ip it says my connection is active. When attempting to ping the Master in a command prompt I get "destination host unreachable". Any help would be greatly appreciated!
set ping_ip=1.1.1.1
set failure_count=0
set timeout_secs=300
set connection_error_count=0
set max_connection_error_count=3
:start
:: calling the ping function
call :connection_test
:: Processing the network "up" state
if "%network_state%"=="up" (
echo INFO: You have an active connection.
set connection_error_count=0
) else (
set /a connection_error_count+=1
)
:: Processing the network "down" state
if "%network_state%"=="down" (
if %connection_error_count% geq %max_connection_error_count% (
echo ERROR: You do not have an active connection.
goto poweroff
) else (
echo INFO: FAILURE: That failed [%connection_error_count%] times, NOT good. lets try again...
goto start
)
)
timeout /t %timeout_secs%
goto start
:: connection_test function
goto skip_connection_test
:connection_test
:: Getting the successful ping count
echo INFO: Checking connection, please hang tight for a second...
for /f "tokens=5 delims==, " %%p in ('ping -n 4 %ping_ip% ^| findstr /i "Received"') do set ping_count=%%p
:: Check the ping_count against the failure_count
if "%ping_count%" leq "%failure_count%" (
set network_state=down
) else (
set network_state=up
)
goto :eof
:skip_connection_test
:: Power off
:poweroff
echo INFO: Shutdown PC in 60 seconds. Press any key to abort.
shutdown -s -t 60 -f
pause > nul
shutdown -a
goto end
:end ```
Your code is quite large for something so simple. First, the address you set on ipv4 is not the correct address!
You can access my repository to read how to acquire your IPv4 code here.
After obtain your IPv4 address, add to your code:
ping %ipv4% -n 9 | findstr /i "unreach">filex.txt
set /p stop=<filex.txt
if "%stop%" neq "" (
:: put here your shutdown preferences.
)
If you want something like what you are searching for:
#echo off
:verif
set points=
echo INFO: Checking connection, please hang tight for a second...
ping %ipv4% -n 3 | findstr /i "unreach">filex.txt
set /p stop=<filex.txt
if "%stop%" neq "" set /a points=%points%+1
del /q /f filex.txt
ping %ipv4% -n 3 | findstr /i "unreach">filed.txt
set /p stopd=<filed.txt
if "%stopd%" neq "" set /a points=%points%+1
:: Add points as you want.
if "%points%" geq "2" (
set shutdown=y
)
if "%shutdown%" equ "y" (
echo ERROR: You do not have an active connection.
shutdown -s -t 60 -f
echo INFO: Shutdown PC in 60 seconds. Press any key to abort.
pause>nul
shutdown -a
goto verif
)
echo INFO: You have an active connection.
goto verif
Hope this helps,
K.
I used the code provided in the best answer in this thread: Need auto-restart script in batch for minecraft server
However, I'm not sure when the choice function is supposed to run.
Furthermore, I'd rather not have a choice option. I'd like the server just to give a 60 second heads up that it's going to restart and then execute the restart.
Any help would be appreciated!
Here's the code from the previous answer:
#echo off
title minecraft-server-1.8.3
color 0A
prompt [server]:
cls
:start
echo loading server...
java -Xms3G -Xmx3G -jar minecraft_server.1.8.3.jar nogui
cls
:choice
set /P a=do you want to restart[Y/N]?
if /I "%a%" EQU "Y" goto :restart
if /I "%a%" EQU "N" goto :stop
goto :choice
:restart
cls
echo server will restart
TIMEOUT /T 5
cls
goto :start
:stop
cls
echo closing server
TIMEOUT /T 5
exit
Welcome to stack overflow.
As #Mofi mentioned in a comment, you can use TIMEOUT to create wait statement
The script you might want would look something like this:
:start
echo loading server...
java -Xms3G -Xmx3G -jar minecraft_server.1.8.3.jar nogui
cls
REM I recommend NOT using TIMEOUT /T for the main wait, this way you can skip it and initiate a restart immediately
TIMEOUT 10720
REM 3 hours minus 60 seconds to allow for 60 second restart notification
cls
echo server will restart
TIMEOUT /T 60
cls
goto :start
(Since you seem to be somewhat new to batch, REM is used to comment out lines)
To answer your question surrounding why the :choice section is a thing:
It is initiated after the :start section, allowing you to either (Y) restart, or (N) stop the server
I try to write a little batch script. It should play a sound if my phone joins my network.
#echo off
:A
ping -n 1 xxx.xxx.xxx.xx | findstr TTL && start airsiren.wav
goto A
The problem is now that if the phone is detected, it repeatedly starts the sound. But it's supposed to just play once.
Does anyone know a simple fix? Maybe with an IF condition?
I haven't been doing much with batch, but I think I got some basic knowledge.
I suggest following code:
#echo off
set "LastExitCode=1"
:Loop
%SystemRoot%\System32\ping.exe -n 1 xxx.xxx.xxx.xx | %SystemRoot%\System32\find.exe /C "TTL" >nul
if not %ErrorLevel% == %LastExitCode% set "LastExitCode=%ErrorLevel%" & if %ErrorLevel% == 0 start "Play sound" airsiren.wav
%SystemRoot%\System32\timeout.exe /T 5 /NOBREAK
if not errorlevel 1 goto Loop
PING outputs a line with TTL if there is a response on echo request and exits usually with value 0 on receiving a response and with 1 on getting no response. But PING does not always exit with 0 on a positive response which is the reason for using FIND.
FIND processes the output of PING and searches for lines containing the string TTL. FIND exits with value 0 on finding at least one line with TTL and otherwise with 1 for indicating no line found containing the search string. The output of FIND to handle STDOUT is of no interest and therefore reduced to a minimum by using option /C and redirected to device NUL.
Now the exit code of FIND is compared with an environment variable which holds last exit value of FIND initialized with value 1.
On current exit code being equal last exit code, there is no change in availability of the pinged device on network and therefore nothing to do.
Otherwise on a difference the current exit code is assigned to the environment variable for next loop run and current exit code is compared with value 0. If this second condition is true the pinged device sent the first time a positive response on echo request by PING. In this case the sound is played.
There is nothing else done on pinged device not available anymore on network, i.e. the exit code changes from 0 to 1.
Then a delay of 5 seconds is started using TIMEOUT with giving the user to break it with Ctrl+C. This reduces the processor core usage giving Windows the possibility to use the processor core for other processes and also reduces network usage when the pinged device is available at the moment on network. And of course the pinged device does not need anymore to permanently response on echo requests.
A jump to label Loop is done if TIMEOUT exited normally without a user break. Otherwise on user pressing Ctrl+C the batch file processing also ends.
TIMEOUT with parameter /NOBREAK requires Windows 7 or a later Windows version.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
echo /?
find /?
goto /?
if /?
ping /?
set /?
start /?
timeout /?
See also single line with multiple commands using Windows batch file for an explanation of operator & and meaning of if not errorlevel 1.
This can be fixed very easily using %errorlevel% and an IF statement.
Original script by Jelle Geerts.
#ECHO OFF
:Search
ping -n 1 "xxx.xxx.xxx.xx" | findstr /r /c:"[0-9] *ms"
if %errorlevel% == 0 (
echo Device was found!
start airsiren.wav
pause.
) else (
goto Search
)
My solution:
#echo off &:: modem_tester_xp+.bat
REM original https://www.elektroda.pl/rtvforum/topic2917839.html
setlocal EnableDelayedExpansion
rem set connection name (for newer than Win XP) from Network Connections (preferred name doesn't have space)
set _connection_name=internet
rem make file which close this script
echo #echo.^>"%~dpn0.exit"^&#del /q "%%~f0">"%~dp0close_%~nx0"
for /f "tokens=2-4 delims==." %%a in ('wmic os get Version /value ^|find "="') do if "%%~c" neq "" set "_system_version=%%~a.%%~b"
set "_con_ip="
set "_my_ip.last="
:start
::-n (seconds+1)
ping 127.0.0.1 >nul -n 3
set "_my_ip="
if not defined _con_ip call :get_con_ip "%_connection_name%"
if defined _con_ip for /f "tokens=3-5 delims= " %%p in ('route print ^|find " 0.0.0.0 "') do if "%%~r" neq "" if /i "%%~p"=="%_con_ip%" ( set "_my_ip=%%~p" ) else if /i "%%~q"=="%_con_ip%" set "_my_ip=%%~q"
rem if connection lost clean variable _my_ip.last
if not defined _my_ip (
set "_con_ip="
set "_my_ip.last="
) else if /i "%_my_ip%" neq "%_my_ip.last%" (
rem remember last connection addres
set "_my_ip.last=%_my_ip%"
call :2run
)
if not exist "%~dpn0.exit" goto start
del /q "%~dpn0.exit"
endlocal
goto :eof
:get_con_ip &::ConnectionName:return variable _con_ip
if "%_system_version%"=="5.1" (
rem XP find modem address
for /f "tokens=2 delims== " %%a in ('netsh diag show gateway WAN* ^|find "." ^|find "="') do if "!_con_ip!"=="" set "_con_ip=%%~a"
) else (
rem if newer works like win7, if not: if "%_system_version%"=="6.1" (rem Windows 7
if "%~1" neq "" for /f "tokens=1,4* delims= " %%n in ('netsh interface ipv4 show interfaces ^|find /i "%~1"') do if "!_con_ip!"=="" if /i "%%~p"=="%~1" for /f "tokens=1* delims=:" %%i in ('netsh interface ipv4 show addresses %%~n ^|find "." ^|find /i "ip"') do if "!_con_ip!"=="" set "_con_ip=%%~j"
if "!_con_ip!" neq "" set "_con_ip=!_con_ip: =!"
)
goto :eof
:2run
rem run external
rem start "modem started" /min /b cmd /c "echo %date% %time% '%_my_ip%'&pause"
start airsiren.wav
There are two problems with your code
Your code will unconditionally goes to the beginning even after the phone is connected, so it repeats playing the sound. You could use ... && (start airsiren.wav & goto :EOF) to terminate the batch file or use another label other than :EOF to do something else. But this doesn't give you the option to keep monitoring the phone for disconnection and re-connection.
You have to check the setting of the default media player (Typically Windows Media Player) and make sure that it is not set to continuously loop or repeat the media. Also it is overkill and somewhat inconvenient to launch a full fledged media player just for playing back a short notification sound, and usually you have to close the media player afterwards.
So this is the code I propose which solves the above mentioned obstacles by providing the option to continuously monitor the phone's connection status and also provide a more programmatic way to play the notification sound in a self contained player by using a hybrid BAT/JSCript solution.
#if (#Code)==(#BatchScript) /* Hybrid BAT/JScript line */
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set #PlaySound=start "" /b cscript //nologo //e:JScript "%~f0"
set "SoundFile.Connect=%SystemRoot%\media\ringout.wav"
set "SoundFile.Disconnect=?"
set "GenFail.Localized.Text=General failure"
:: set to 0 to disable continuous connection monitoring
set "ContinuousMonitoring=1"
set "PhoneIP=xxx.xxx.xxx.xxx"
set "Timeout=3000"
setlocal EnableDelayedExpansion
set "CheckGeneralFailure=1"
echo [%TIME%] Waiting for connection...
:WaitForConnection
ping -n 1 %PhoneIP% -w %Timeout% | findstr "TTL" >nul && (
echo [!TIME!] Phone Connected.
!#PlaySound! "!SoundFile.Connect!"
if %ContinuousMonitoring% NEQ 0 goto :MonitorConnection
goto :EOF
) || (
if !CheckGeneralFailure! NEQ 0 (
ping -n 1 %PhoneIP% -w 100 | findstr /i /c:"%GenFail.Localized.Text%" >nul && (
ping -n 1 -w %Timeout% 127.255.255.255 >nul
(call,) %= Set errorlevel to 0 =%
) || set "CheckGeneralFailure=0"
)
goto :WaitForConnection
)
:MonitorConnection
ping -n 1 %PhoneIP% | findstr "TTL" >nul && (
ping -n 1 -w %Timeout% 127.255.255.255 >nul
goto :MonitorConnection
) || (
echo [!TIME!] Phone Disconnected.
echo [!TIME!] Waiting for connection...
set "CheckGeneralFailure=1"
REM Play another sound for disconnect?
goto :WaitForConnection
)
goto :EOF
/*** End of batch code ***/
#end
/*** JScript Sound Player ***/
var wmpps = {
Undefined : 0,
Stopped : 1,
Paused : 2,
Playing : 3,
ScanForward : 4,
ScanReverse : 5,
Buffering : 6,
Waiting : 7,
MediaEnded : 8,
Transitioning : 9,
Ready : 10,
Reconnecting : 11,
Last : 12
};
var SoundFile;
if (WScript.Arguments.length) SoundFile = WScript.Arguments(0);
var WaitCount = 0;
var objPlayer = new ActiveXObject("WMPlayer.OCX.7");
with(objPlayer) {
URL = SoundFile;
settings.volume = 100;
settings.setMode("loop", false);
controls.play();
while(playState == wmpps.Transitioning) {
WaitCount+=1;
if (WaitCount > 200) break;
WScript.Sleep(10);
}
if (playState == wmpps.Playing) {
while(playState != wmpps.Stopped) WScript.Sleep(1000);
}
close();
}
Looking to use findstr to get it to find "0% loss" after a ping command.
Perhaps an array of anything up to "50% loss".
This is for checking and ensuring a connection to the internet is 100% established before launching something online.
Currently it's structured:
ping %ip% -n 3 -w 3000 | findstr "0% loss"
pause
goto Starting
It's currently ignoring findstr and no matter what it refuses to find what I'm looking for
Ideally it would flow like:
ping %ip% -n 3 -w 3000 | findstr "0% loss" || goto Echo
pause
goto Starting
:echo
Could not find "0% loss"
pause
And I have tried that, it will go to echo, but even with 100% connection so it's clearly just not operating how I'd like it to.
Is there a better way to find % packet loss?
Or
Is there a better way to test internet connection, given ping doesn't work when a device is totally offline.
The search string you are looking for is too broad. When you check findstr for "0% loss", you are inadvertently picking up "100% loss" as well. Fortunately, ping puts the packet loss in parentheses, so you can simply include the open parenthesis in the search string.
#echo off
title Restart
color 0A
cls
:start
Cls
set ip=www.google.com
:Pingcheck
echo Checking ping..
timeout /t 3
ping %ip% -n 5 -w 3000 | findstr /C:"(0% loss" || goto Loss
pause
:NoLoss
echo We found 0 packet loss, at %ip% on %date% at %time%
pause
goto start
:Loss
echo We found some packet loss.
pause
I've also changed the name of the :Echo label because echo is already a command and having it also be a label would be confusing.
You can also check ping status with wmi. The advantage to this method is that it'll goto :fail on the first failure, and not continue its lost cause of completing 5 ping attempts, while also providing a simple way to preserve the average response time. It uses set /a to check whether the result of the wmi query contains a numeric value. If it does, pass. If not, fail.
#echo off & setlocal
set "host=www.google.com"
echo Pinging %host%...
for /L %%I in (1,1,5) do (
for /f "delims=" %%x in (
'wmic path win32_pingstatus where "address='%host%' and timeout=3000"^
get ResponseTime /value ^| find "="'
) do (
2>NUL set /a "%%x, avg += ResponseTime" || goto fail
)
)
set /a "avg /= 5"
echo 0%% packet loss. Woo. Average response time was %avg%ms.
exit /b
:fail
echo Aw snap. Packet loss.
i've seen pingers and auto redials when theres a request time out.
problem:
but im having a hard time researching the 'counter or increment' part.
idea:
heres how it should be:
start pinging continuously while connected to internet,
otherwise
count (or accumulate) request time out until 1min or 60 request time out,
if connection went back after request time out & less than '60 times request time out',reset the
'request time out counter' to zero
if request time out reached 60x :
run another batch or reconnect re-dial up.
loop to internet connection pinging
the closest that i saw:
(but for some reason its not working on my xp)
#echo off
setLocal EnableDelayedExpansion
:loop
ping -n 2 10.174.10.48 >> log
find /i "Reply" < log > nul
if not errorlevel 1 type nul > log & goto :loop
for /f "tokens=1" %%a in ('find /c /i "Request timed out" ^< log') do (
if %%a geq 10 echo file.exe && type nul > log
)
goto :loop
source: http://www.computing.net/answers/programming/ping-bat-file/16605.html
credits to the original poster.
thank you
It would be good to know why the above script is not working. Because possibly other solutions will also not work. If you use a non-English version of windows, you need to replace the text "Reply".
I think the following should work. It just implements the counter. But you can try yourself how you need to set the counter to execute the script after 60 seconds.
#echo off
:reset
set count=0
:loop
ping -n 2 10.174.10.48 | find /i "Reply"
if not errorlevel 1 goto :reset
set /A count=%count%+1
if %count% lss 100 got :loop
call reconnect
goto :reset