How do I ping the default gateway without specifying the IP address? - windows

I'm trying to write a batch file that tests network connectivity by pinging the default gateway of the given network.
However, as I want this to be an automated process which then logs the results to a text file, I'd like to be able to ping the gateway on various networks, without having to change/enter the ip address.
Is there a generic term or command to ping the default gateway for the network you're currently connected to?
(I already have the commands for output options etc.)
So far, I have this....
#echo off
goto :NETWORK1
:NETWORK1
ipconfig
echo .
Set /P gateway=PLEASE ENTER GATEWAY IP ADDRESS (shown above):
if /I "%gateway%" EQU "exit" goto :EXIT
if /I not "%gateway%" EQU "exit" goto :NETWORK2
:NETWORK2
echo CLOSING THIS WINDOW WILL ABORT THE CONNECTIVITY TEST.
echo . >> "C:\Network Test Results %date:/=.%.txt"
echo Time: >> "C:\Network Test Results %date:/=.%.txt"
time /t >> "C:\Network Test Results %date:/=.%.txt"
ping %gateway% -n 20 >> "C:\Network Test Results %date:/=.%.txt"
goto :NETWORK2
:EXIT
exit
But I don't want to have to specify the IP address, so that I can take away the need for user input.

smalll fix for Wernfried Domscheit
for /f "tokens=2 delims=:" %%g in ('netsh interface ip show address ^| findstr /c:"Default Gateway"') do ping %%g
pause
just adding /c: before "Default Gateway"

On a command line you can try this one:
for /f "tokens=2 delims=:" %g in ('netsh interface ip show address ^| findstr "Default Gateway"') do ping %g
Note, inside a batch-file you must double the %, i.e.
for /f "tokens=2 delims=:" %%g in ('netsh interface ip show address ^| findstr "Default Gateway"') do ping %%g

According to jimbobomcgee on serverfault who phrased the correct answer for the question How to Extract command-line output into a Variable?
for /f "usebackq tokens=1,2,3 delims=:" %A in (`ipconfig ^| Find "Default Gateway" ^| Findstr/N "." ^| Findstr/B "1:"`) do #if not defined MYVAR set MYVAR=%~C

#echo off
setlocal enableextensions disabledelayedexpansion
set "gateway="
for /f "tokens=1-5" %%a in ('route -4 print 0.*') do #if "%%e"=="" if "%%a"=="%%b" set "gateway=%%c"
if not defined gateway goto :eof
echo CLOSING THIS WINDOW WILL ABORT THE CONNECTIVITY TEST.
:loop
echo %date% %time%
>> "Network Test Results %date:/=.%.txt" (
echo(
echo(Time: %time%
ping -n 20 -4 %gateway%
)
goto :loop
Gateway determination from route information copied from here
edited for a more tolerant parse of the route command use
for /f "tokens=3" %%a in ('route -4 print 0.* ^| find "0."') do set "gateway=%%a"

After help from #MC ND, I have created the following code, which does exactly what I needed....
pings the default gateway with the results being output to a text file
shows a message telling the user not to close the command window
#echo off
setlocal enableextensions disabledelayedexpansion
for /f "tokens=3" %%a in ('route -4 print 0.*') do set "gateway=%%a"
:NETWORK
echo CLOSING THIS WINDOW WILL ABORT THE CONNECTIVITY TEST.
echo Time >> "C:\Network Test Results %date:/=.%.txt"
time /t >> "C:\Network Test Results %date:/=.%.txt"
echo . >> "C:\Network Test Results %date:/=.%.txt"
ping %gateway% -n 20 >> "C:\Network Test Results %date:/=.%.txt"
goto :NETWORK

Related

Adding names to an IP address without failing the batch file

I want to use a batch file to ping a set of servers. The batch file works and reports ok or failed. All I want is to have it display a name of the server in the check.
This is what I use in the batch file:
#echo off
for /f "delims=" %%a in (C:\List of IPs.txt) do ping -n 1 %%a >nul && (echo %%a ok) || (echo %%a failed to respond)
pause
In the text file it points to is just a list of IPs, how do I make it so I can see a name next to the IP?
Thank you in advance!
just insert another for /f loop to get the name:
#echo off
SetLocal
for /f "usebackq" %%a in ("List of IPs.txt") do (
for /f %%b in ('"ping -n 1 %%a >nul && (echo ok) || (echo failed to respond) "') do (
for /f "tokens=1*" %%m in ('nslookup %%a ^|findstr /b "Name:"') do (
echo %%a %%n %%b
)
)
)
One option is to format your file to have the IP and the name you are interested in.
192.168.1.200 server1
192.168.1.201 server2
192.168.1.202 printer1
192.168.1.203 that one stupid printer in the back
Then you can read both from the file.
One thing I'll note -- your method of checking pings is not consistent. You can get an errorlevel 0 even if the ping actually fails (from a valid response of "unreachable"). Instead (in English) a successful ping always includes "ttl=". Thus you would do this:
untested
#echo off
for /f "usebackq tokens=1* delims= " %%a in ("C:\List of IPs.txt") do ping -n 1 %%a ^|find /i "ttl=" >nul && (echo %%b at %%a is ok) || (echo %%b at %%a failed to respond)
pause
nslookup and/or ping -a can be leveraged if you have dns working with everything you're trying to access.
Based on comment, I've added the following solution that works on my English Windows 10 computer with the text file above:
#echo off
for /f "usebackq tokens=1* delims= " %%a in ("C:\temp\List of IPs.txt") do ping -n 1 -w 1500 %%a |find /i "ttl=" >nul &&echo %%b at %%a is ok||echo %%b at %%a failed to respond
pause
Note there is a space between the equal sign and the double quote at delims= "
Output:
server1 at 192.168.1.200 is ok
server2 at 192.168.1.201 is ok
printer1 at 192.168.1.202 is ok
that one stupid printer in the back at 192.168.1.203 failed to respond
Press any key to continue . . .

Windows Batch - How to get the external IP into a batch-file variable

I am making a program that checks if a user's IP is a certain IP address.
Currently, I created a successful internal IP version:
#echo off
set userIp=192.168.90.100
for /f "tokens=4 delims= " %%i in ('route print ^| find " 0.0.0.0"') do set localIp=%%i
for /f "delims=[] tokens=2" %%a in ('ping %computername% -4 -n 1 ^| findstr "["') do set thisip=%%a
goto :Check
:Check
if %localIp%==%userIp% goto :Good
if %thisip%==%userIp% goto :Good
goto :Bad
And I am trying to make the same thing that works with external IPs.
I researched online, and here is what I got so far.
#echo off
for /f "tokens=2 delims=:" %%a IN ('nslookup myip.opendns.com. resolver1.opendns.com ^| findstr /IC:"Address"') do if /i %%a=="10.11.12.13" goto :Good
goto :Bad
I need a bit of help on how to fix this.
With pure batch/already present tools:
EDIT: changed the batch to properly handle also IPv6 addresses
#Echo off
for /f "tokens=1* delims=: " %%A in (
'nslookup myip.opendns.com. resolver1.opendns.com 2^>NUL^|find "Address:"'
) Do set ExtIP=%%B
Echo External IP is : %ExtIP%
Reference
Another one with powershell:
#Echo off
For /f %%A in (
'powershell -command "(Invoke-Webrequest "http://api.ipify.org").content"'
) Do Set ExtIP=%%A
Echo External IP is : %ExtIP%
And another slightly different powershell variant:
#Echo off
For /f %%A in (
'powershell -nop -c "(Invoke-RestMethod http://ipinfo.io/json).IP"'
) Do Set ExtIP=%%A
Echo External IP is : %ExtIP%
To get your public IP without additional parsing do this:
curl "http://api.ipify.org"
EDIT:
This version is more reliable across windows language versions:
for /f "tokens=3 delims== " %%A in ('
nslookup -debug myip.opendns.com. resolver1.opendns.com 2^>NUL^|findstr /C:"internet address"
') do set "ext_ip=%%A"
First it seems there is a . too much after the first .com.
Second when using your command with simply google.com and echo %a I get the following:
" xx.xx.xx.x" without the quotes and with two leading spaces!
So your if will never be true!
Change it to something like this: if "%%a"==" xx.xx.xx.x" Goto:good and you should be fine.

How to merge two .bat file commands to function as one?

Here is what I've been using:
PING -n 1 10.0.0.1|find "Reply from" >NUL
IF NOT ERRORLEVEL 1 goto :PASS
IF ERRORLEVEL 1 goto :FAIL
But this only works if the IP matches.
So, I found these commands on this site (in an answer by Wernfried Domscheit) that seem to work on their own but I don't know how to incorporate them together:
In a Batch file:
for /f "tokens=2 delims=:" %%g in ('netsh interface ip show address ^| findstr "Default Gateway"') do ping %%g
At the cmd prompt:
for /f "tokens=2 delims=:" %g in ('netsh interface ip show address ^| findstr "Default Gateway"') do ping %g
Any advice?
Instead of checking if the ping output contains "Reply from", it's better to search for "TTL=":
ping -n 1 10.0.0.1| findstr "TTL="
as pointed in this answer. Searching for "TTL=" after a ping will be more reliable than searching for "Reply from". There are some ping error messages with "Reply from". In some cases you can get a reply from another machine stating that the machine you're looking for is not reachable for example. You'll then have a "Reply from" in the failed ping output.
If you want to use the ping with the findstr and its errorlevel in a for loop you cannot not use goto to jump to a label. The goto will destroy your loop context. You can see goto as a command that tells the parser to abandon the command it was processing/executing (the FOR loop) and start at the label you gave as argument. It will just forget about the loop.
I will assume your labels are arranged this way:
:PASS
rem some commands in case the ping succeeded
<commands_succes>
goto :BOTH
:FAIL
rem some code in case the ping failed
<commands_fail>
:BOTH
rem code that has to be executed in both cases after code for individual case (if any)
<commands_after>
Your loop can then take these different forms:
using IF ERRORLEVEL 1 ( ... ) ELSE ( ) and move all code from the :FAIL label to the if-branch and all code from the :PASS label to the else-branch. The code from the :BOTH label (if any) will come under the whole if-block
for /f "tokens=2 delims=:" %%g in ('netsh interface ip show address ^| findstr /C:"Default Gateway"') do (
ping %%g | findstr "TTL=">NUL
IF ERRORLEVEL 1 (
rem Here comes code in case the ping failed (code for :FAIL label)
<commands_fail>
) ELSE (
rem Here comes code in case the ping succeeded (code for :PASS label)
<commands_succes>
)
rem code that has to be executed in both cases after code for individual case (if any)
<commands_after>
)
use function calls with the call command instead of goto. If the call command is used with labels it does the same as the goto except that the parser will remember its state (command it was executing) and will come back to it after the execution of the label is exited. so it will execute commands from the label untill an explicit exit, goto :EOF or end of file is encountered.
for /f "tokens=2 delims=:" %%g in ('netsh interface ip show address ^| findstr /C:"Default Gateway"') do (
ping %%g | findstr "TTL=" > NUL
IF ERRORLEVEL 1 (
rem ping failed
call :FAIL
) ELSE (
rem ping succeeded
call :PASS
)
)
exit /b 0
:PASS
rem some commands in case the ping succeeded
<commands_succes>
goto :BOTH
:FAIL
rem some code in case the ping failed
<commands_fail>
:BOTH
rem code that has to be executed in both cases after code for individual case (if any)
<commands_after>
exit /b 0
Both cases should work for you. You'll just have to copy-paste the code corresponding to the <commands_fail>, <commands_success> and <commands_after> on the right places. If you don't have anything in <commands_after> you can just leave it blank.
EDIT: Thanks to #Josefz who noticed a little mistake I missed in the command you use in the FOR loops to get the IP address of the default gateway:
netsh interface ip show address | findstr "Default Gateway"
The issue is that findstr uses whitespace as delimiter for its regular expressions (whitespace in findstr = | in grep = OR operator). So what it will be looking for in the case above is Default or Gateway and will not only give you the default gateway but also the gateway metric which isn't even an IP address. Use the /C switch of findstr to make it look for litteral string Default Gateway:
netsh interface ip show address | findstr /C:"Default Gateway"
I've corrected it in the code samples above as well.
Good luck!
PS: In both cases you can use conditional execution instead of checking the errorlevel. Follow the link for more info but be sure to read the note also!
Although not clearly stated, i'll assume that you want to use the IP found by your second command in the first one. That's simply:
for /f "tokens=2 delims=:" %%g in ('netsh interface ip show address ^| findstr "Default Gateway"') do SET IP=%%g
PING -n 1 %IP%|find "Reply from" >NUL
IF NOT ERRORLEVEL 1 goto :PASS
IF ERRORLEVEL 1 goto :FAIL
You set a variable (IP) in the for statement, and use it instead of the fixed ip in the ping.

Windows batch file - ipconfig / skype

I want that Skype only starts when I am connected on a specific LAN IP address.
#echo off
set ip_address_string="IPv4 Address"
for /f "usebackq tokens=2 delims=:" %%f in (`ipconfig ^| findstr /c:%ip_address_string%`) do echo bounded IP-address: %%f
But how can I realize that Skype only will be called if any ip address contains 64.2.4.*?
Moreover, the batch file will run every 5 minutes and if it is required the Skype-process should be killed.
#echo off
set "ip_address_string=64.2.4."
ipconfig | findstr /c:"%ip_address_string%" >nul|| (
echo IP "%ip_address_string%" not found.
taskkill /im skype.exe /f
exit /b 0
)
echo connected as/to "%ip_address_string%"
?

Batch ping a list of computer names and write the results to file

The code below will write the computer name and ip address to file, but I would like it to also write the name of the computers it cannot ping with a fail next to it. I have no idea how I would modify the batch file to do this.
#echo off
Echo Pinging list...
set ComputerList=list.txt
Echo Computername,IP Address>Final.csv
setlocal enabledelayedexpansion
for /f "usebackq tokens=*" %%A in ("%ComputerList%") do (
for /f "tokens=3" %%B in ('ping -n 1 -l 1 %%A ^|findstr Reply') do (
set IPadd=%%B
echo %%A,!IPadd:~0, -1!>>Results.csv
))
pause
You could use errorlevel set by findstr to substitute return string(s) if 'Reply' is not found:
('ping -n 1 -l 1 %%A ^|findstr Reply ^|^| echo Not found Failed:')
where || (escaped here because of for context with ^) means execute only if previous command failed.
As a side note, you should be aware that ping messages are system language dependent (they are translated to language of OS) so 'Reply' as success indicator works only for English versions.
This may not be directly what you are looking for, but I had a similar task: run ping and report success or failure. I'll leave extracting the IP address to you - seeing as you have already done it.
The problem with ping is that it returns success upon name resolution, whether packets get lost or host is unreachable (will report 0% Loss) is irrelevant.
FOR %%a IN (
google.com
a.b.c.d
) DO #FOR /F "delims=" %%p IN (
'PING -w 100 -n 1 %%a ^| findstr ^"Reply Request fail name^"'
) DO #(
ECHO "%%p" | FINDSTR TTL >2 && echo %%a, success, %%p || echo %%a, failed, %%p
) >> Results.csv
Logic: Ping once, filter only lines with the one of the words listed. If TTL exists in resulting line (output to STDERR or NUL to avoid output pollution) echo success, else echo failed.
I'm on English Windows, words will have to be adjusted for other languages.
EDIT:
FOR %%a IN (
google.com
a.b.c.d
) DO #FOR /F "delims=" %%p IN ('PING -n 1 %%a ^| findstr TTL ^|^| echo Failed') DO #(
ECHO "%%p" | FINDSTR TTL >2 && (for /f "tokens=3" %%b IN ("%%p") do #echo %%a, %%b) || echo %%a, failed, %%p
)
Less dependant on language, works only for IPv4, added IP extraction.
Filter ping output for TTL, set output to "Failed" if TTL not found.
If output string contains TTL, extract IP and echo host and IP, else echo host name and output string.

Resources