Hi so my coworker requested if I could make a script. I am sure what I want it to do and wrote some pseudo code in bash style now of course this not useable for him since he is on Windows. So I tried to implement in a .bat script now here is where my knowledge comes a bit short. What I need the script to do is to connect to a certain VPN-ip if that is not avaible the localsystem should foward it to another VPN so he doesn't need to worry about it. Either one of 2 should always be reachable. But they are never at the same time. This is for test tooling.
Pseudo bashcode
while true
do
From local if
10.10.1.15 avaible connect to it
else
10.168.84.47 connect to it
elseif
try to connect to 10.10.1.15 again && verify that'
else
echo 'error device over VPN unavaible'
My Attempted batch script, I am pretty sure that what I have now is not gonna work
#setlocal enableextensions enabledelayedexpansion
#echo off
set ipaddr=%1
:loop
set state=down
for /f "tokens=5,6,7" %%a in ('ping -n 1 !ipaddr!') do (
if "x%%b"=="xunreachable." goto :endloop
if "x%%a"=="xReceived" if "x%%c"=="x1," set state=up
)
:endloop
echo.Link is !state!
ping -n 6 10.10.1.15 >nul: 2>nul:
goto :loop
endlocal
IF EXIST 10.10.1.15 (
is reacheable connect
) ELSE (
netsh interface portproxy add v4tov4 listenport=80 connectaddress=10.10.1.15 fowardaddress=10.168.84.47
)
So far as I know, you can just try to find "ttl=" to determine success/fail for a ping without worrying about all those tokens and different versions of cmd. I'm sure someone will correct me if I'm wrong.
untested
set ip=127.0.0.1
rem 2 pings waiting 900ms for a reply
ping -n 2 -w 900 %ip%|find /i "ttl=">nul || goto :fail
rem If we get here then the ping succeeded
rem do what you want here
goto :eof
:fail
rem If we get here then the ping failed.
rem do what you want here
goto :eof
The || operator basically means "if the previous command fails then do this".
With Windows 10 is it possible to setup up known networks and be able to connect to them without all the mouse movement and click?
Using Windows batch files, you can set it up to connect to networks you already know (Network1 or Network2, below) without ever touching the mouse.
#echo off
setlocal EnableDelayedExpansion
for %%i in ("Network1"
"Network2") do (
netsh wlan show networks mode=ssid | findstr /C:%%i
if !ERRORLEVEL! EQU 0 (
echo "Found %%~i - connecting..."
netsh wlan connect name=%%i
exit /b
) else (
echo "Did not find %%~i"
)
)
#echo on
Save the above to .bat and run it from cmd.exe or a program like Listary.
Some comments about the code:
If more than one of your listed networks are available, it will connect to whichever is first in the for loop list. You could also put the list in a file and change for %%i to for /F %%i
EnableDelayedExpansion and "!" around ERRORLEVEL
are needed to keep the variable ERRORLEVEL from being assigned
whatever it was at the beginning of the script. Since I don't
normally program Windows batch files, this is 2 hours of my life
gone that you won't have to deal with.
All the echoing is for debugging; the echo off at the top squelches it.
%% needed for variables in Windows batch files. The variable is referenced with % at the command line.
%%~i strips the quotation marks around the string when outputting to stdout.
Is it possible to retrieve the data output when you type ping in the command line?
Currently, we have existing servers that we check daily by typing ping (IP address) in the command line but only during at the start of the day. We would only be notified if the server is down once the user notifies us. The manual thing to do is to do a continuous ping and do a timely check of whether it was disconnected or not.
I would like to create something that would give out a prompt (while doing a continuous ping in the background) once the command line declares that there's a "request time out", intermittent connection, etc. So that there wouldn't be a need to manually check the status of the connection.
I realize this was asked 2 months ago, but it was never answered. Hopefully this will still be useful to someone. Granted, it's much easier to implement using a "real" programming language, but sometimes you need something that uses only built-in commands.
Configure as needed via environment variables (examples shown). To be polite, you probably want to use much longer timeouts if you don't own the server you're pinging.
#echo off
cls
setlocal enabledelayedexpansion
REM Configuration:
set SERVER=google.com
set TIMEOUT_AFTER_PING_FAIL_SECONDS=5
set TIMEOUT_AFTER_PING_SUCCEED_SECONDS=10
set TIMEOUT_AFTER_LINK_DOWN_SECONDS=15
set DECLARE_LINK_DOWN_FAILS=5
set CONSECUTIVE_FAIL_COUNT=0
:Start
set PING_RESULT=Failure
for /f "delims=" %%X in ('ping /n 1 %SERVER%') do (
set TEMPVAR=%%X
if "Reply from"=="!TEMPVAR:~0,10!" set PING_RESULT=Success
)
goto:!PING_RESULT!
:Success
echo Ping Succeeded
set CONSECUTIVE_FAIL_COUNT=0
call:Sleep %TIMEOUT_AFTER_PING_SUCCEED_SECONDS%
goto:Start
:Failure
set /A CONSECUTIVE_FAIL_COUNT+=1
echo Ping Failed !CONSECUTIVE_FAIL_COUNT! Time(s)
if !CONSECUTIVE_FAIL_COUNT!==%DECLARE_LINK_DOWN_FAILS% (call:LinkDownHandler&goto:Start)
call:Sleep %TIMEOUT_AFTER_PING_FAIL_SECONDS%
goto:Start
:Sleep
REM See http://stackoverflow.com/questions/4317020/windows-batch-sleep
setlocal
set /A ITERATIONS=%1+1
ping -n %ITERATIONS% 127.0.0.1 >nul
goto:eof
:LinkDownHandler
echo Link is Down
set CONSECUTIVE_FAIL_COUNT=0
REM Add additional link-down handler actions here
call:Sleep %TIMEOUT_AFTER_LINK_DOWN_SECONDS%
goto:eof
I'm trying to use a batch file to confirm a network connection using ping. I want to do batch run and then print if the ping was successful or not. The problem is that it always displays 'failure' when run as a batch. Here is the code:
#echo off
cls
ping racer | find "Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),"
if not errorlevel 1 set error=success
if errorlevel 1 set error=failure
cls
echo Result: %error%
pause
'racer' is the name of my computer. I'm having my computer ping itself so I can eliminate the variable of a poor connection. As I said before, the batch always results in failure. Oddly enough, the program works fine if I copy the code into the command prompt. Does anyone know why the program works fine in the command prompt but doesn't work as a batch?
Thanks
A more reliable ping error checking method:
#echo off
set "host=192.168.1.1"
ping -n 1 "%host%" | findstr /r /c:"[0-9] *ms"
if %errorlevel% == 0 (
echo Success.
) else (
echo FAILURE.
)
This works by checking whether a string such as 69 ms or 314ms is printed by ping.
(Translated versions of Windows may print 42 ms (with the space), hence we check for that.)
Reason:
Other proposals, such as matching time= or TTL are not as reliable, because pinging IPv6 addresses doesn't show TTL (at least not on my Windows 7 machine) and translated versions of Windows may show a translated version of the string time=. Also, not only may time= be translated, but sometimes it may be time< rather than time=, as in the case of time<1ms.
If you were to
echo "Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),"
you would see the % is stripped. You need to escape it as % has a special meaning within a batch file:
"Packets: Sent = 4, Received = 4, Lost = 0 (0%% loss),"
However its simpler to use TTL as the indication of success;
.. | find "TTL"
Testing for 0% loss may give a false positive, in this scenario:
Let's say you normally have a network drive on some_IP-address, and you want to find out whether or not it's on.
If that drive is off, and you ping some_IP-address, the IP address from which you ping, will respond:
Answer from your_own_IP-address: target host not reachable
... 0% loss
You might be better off using if exist or if not exist on that network location.
I 'm not exactly sure what the interaction between FIND and setting the error level is, but you can do this quite easily:
#echo off
for /f %%i in ('ping racer ^| find /c "(0%% loss)"') do SET MATCHES=%%i
echo %MATCHES%
This prints 0 if the ping failed, 1 if it succeeded. I made it look for just "0% loss" (not specifically 4 pings) so that the number of pings can be customized.
The percent sign has been doubled so that it's not mistaken for a variable that should be substituted.
The FOR trick serves simply to set the output of a command as the value of an environment variable.
Another variation without using any variable
ping racer -n 1 -w 100>nul || goto :pingerror
...
:pingerror
echo Host down
goto eof
:eof
exit /b
Yes ping fails to return the correct errorlevel. To check the network connection and the computer I used "net view computername" then checked %errorlevel% - simple and easy
First of all
>#echo off
>for /f %%i in ('ping racer ^| find /c "(0%% loss)"') do SET MATCHES=%%i
>echo %MATCHES%
Does not work. If it won't fail, it will detect 0%, because it has 0%.
If it fails, does not work either, because it will have 100% loss, which means, it found the 0% loss part behind the 10
10(0% loss)
Have it detect for 100% loss like so:
>for /f %%i in ('ping -n 1 -l 1 %pc% ^| find /c "(100%% loss)"') do SET check=%%i
Errorlevel might be a bit messed up, but it works like a charm:
>if '%check%'=='1' goto fail
>if '%check%'=='0' echo %pc% is online.&goto starting
1 means it failed
0 means it succeeded
In my script is use links.
Goto fail will go to :fail in my script which will message me that %pc% (which I'll have the user input in the beginning) is offline and will go for another run.
>:fail
>color 0c
>title %pc% is offline
>echo %pc% is offline
>PING -n 6 127.0.0.1>nul
>goto choice
I hope this helps.
The most simple solution to this I can think of:
set error=failure
ping racer -n 1 -w 100>nul 2>&1 && set error=success
Of course, -w needs to be adjusted if on a slow link (100ms might be too short over Dialup ;-))
regards
ping has an errorlevel output value. Success is 0, failure is 1.
Just do this:
C:\>ping 4.2.2.2
Pinging 4.2.2.2 with 32 bytes of data:
Reply from 4.2.2.2: bytes=32 time=28ms TTL=57
Reply from 4.2.2.2: bytes=32 time=29ms TTL=57
Reply from 4.2.2.2: bytes=32 time=30ms TTL=57
Reply from 4.2.2.2: bytes=32 time=29ms TTL=57
Ping statistics for 4.2.2.2:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 28ms, Maximum = 30ms, Average = 29ms
C:\>echo %errorlevel%
0
C:\>ping foo.bar
Ping request could not find host foo.bar. Please check the name and try again.
C:\>echo %errorlevel%
1
As you can see there is no need for all this scripting overkill.
Based on Alex K's note, this works for me on Windows 7:
#echo off
setlocal enableextensions enabledelayedexpansion
for /f %%i in (PCS.TXT) do (
SET bHOSTUP=0
ping -n 2 %%i |find "TTL=" > NUL && SET bHOSTUP=1
IF !bHOSTUP! equ 1 (
CALL :HOSTUP %%i
) else (
CALL :HOSTDOWN %%i
)
)
GOTO EOF
:HOSTUP
echo Host UP %1
GOTO EOF
:HOSTDOWN
echo Host DOWN %1
GOTO EOF
:EOF
exit /B
ping 198.168.57.98 && echo Success || echo failed
I liked the concept of the FIND in the ping results but why not just FIND the Reply from the Address being pinged?
In the example below I enter an IP address as a variable, PING that IP, then look for that variable in the reply string, using the FIND Command.
If the Reply String contains anything other than the correct IP it reports failure.
If you want you can just read the value of ERRORLEVEL from the FIND.
That will give you a reliable value to work with.
#echo off
Set /P IPAdd=Enter Address:
cls
ping %IPAdd% | find "Reply from %IPAdd%:"
if not errorlevel 1 set error=success
if errorlevel 1 set error=failure
cls
echo Result: %error%
pause
I needed to reset a wifi connection because it has issues. This was my quick solution.
#echo off
Rem Microsoft Windows 10 ping test to gateway.
Rem Run batch file from an administrative command prompt.
cls
:starting
Rem Send one ping to the gateway. Write the results to a file.
ping 192.168.1.1 -n 1 > pingtest.txt
Rem Search for unreachable in the file.
c:\windows\system32\findstr.exe "unreachable" pingtest.txt
Rem errorlevel 0 reset the adapter if 1 then wait 10 minutes and test again
if %errorlevel%==1 goto waiting
Rem unreachable was found reset the adapter.
Rem write the date and time the reset was done.
echo Reset date: %date% time: %time% >> resettimes.txt
Rem issue netsh interface show interface to find your adapter's name to reset
Rem my adapter is "wi-fi"
netsh interface set interface "wi-fi" disable
timeout /t 5
netsh interface set interface "wi-fi" enable
:waiting
echo "It is online waiting 10 minutes"
timeout /t 600
goto starting
Reference Iterating arrays in a batch file
I have the following:
for /f "tokens=1" %%Q in ('query termserver') do (
if not ERRORLEVEL (
echo Checking %%Q
for /f "tokens=1" %%U in ('query user %UserID% /server:%%Q') do (echo %%Q)
)
)
When running query termserver from the command line, the first two lines are:
Known
-------------------------
...followed by the list of terminal servers. However, I do not want to include these as part of the query user command. Also, there are about 4 servers I do not wish to include. When I supply UserID with this code, the program is promptly exiting. I know it has something to do with the if statement. Is this not possible to nest flow control inside the for-loop?
I had tried setting a variable to exactly the names of the servers I wanted to check, but the iteration would end on the first server:
set TermServers=Server1.Server2.Server3.Server7.Server8.Server10
for /f "tokens=2 delims=.=" %%Q in ('set TermServers') do (
echo Checking %%Q
for /f "tokens=1" %%U in ('query user %UserID% /server:%%Q') do (echo %%Q)
)
I would prefer this second example over the first if nothing else for cleanliness.
Any help regarding either of these issues would be greatly appreciated.
Again, there are multiple things to note here.
if errorlevel
The help for if says:
IF [NOT] ERRORLEVEL number command
as syntax for the if errorlevel condition. That is, you must provide a number to compare against. Keep in mind that if errorlevel n evaluates to true if the exit code was at least n.
So
if errorlevel 1 ...
catches any error (that is signaled through the exit code), while
if errorlevel 0 ...
simply is always true.
Anyways, you probably want a
if not errorlevel 1 ...
here, since that condition is true if no error occurred.
Skipping lines
The for /f command has an argument skip=n which can be used to skip lines at the start. If your output starts with two lines you don't want, then you can just do
for /f "skip=2 tokens=1" %%Q in ('query termserver') do
Iterating over multiple known values in for /f
The problem with your second code snippet is that for iterates line-wise. So when you give it a single environment variable it will tokenize it (and put the tokens into different variables), but the loop runs only once per line. Also note that using set here is a bit error-prone as you might get more back than you want. Something like
for /f ... in ("%TermServers%") ...
would have been easier. Still, that doesn't solve the original problem. The easiest way to solve this would probably be something like the following:
rem space-separated list of servers
set TermServers=Server1 Server2 Server3 Server7 Server8 Server10
rem call the subroutine with the list of servers
call :query_servers %TermServers%
rem exit the batch file here, to prevent the subroutine from running again afterwards
goto :eof
rem Subroutine to iterate over the list of servers
:query_servers
rem Process the next server in the list
rem Note the usage of %1 here instead of a for loop variable
echo Checking %1
for /f "tokens=1" %%U in ('query user %UserID% /server:%1') do (echo %%Q)
rem Remove the first argument we just processed
shift
rem if there is still another server to be processed, then do so
rem we're mis-using the subroutine label as a jump target here too
if not [%1]==[] goto query_servers
rem This is kind of a "return" statement for subroutines
goto :eof
(untested, but should work.)
ETA: Gah, and once again I miss the most obvious answer:
set TermServers=Server1 Server2 Server3 Server7 Server8 Server10
for %%S in (%TermServers%) do (
for /f "tokens=1" %%U in ('query user %UserID% /server:%1') do (echo %%Q)
)
Note that this is simply for, not for /f and it will dutifully iterate over a list of values. I don't know how I missed that one, sorry.
NT shell/batch language is not smart enough to accept IF NOT ERRORLEVEL (... -- you need to do an explicit comparison, like this:
if not %ERRORLEVEL%==0 (
...