1

I'm making a simple batch script to ping a host and check their connection. This is my code:

@ECHO OFF

@powershell -ExecutionPolicy UnRestricted -Command "(Add-Type -memberDefinition \"[DllImport(\"\"user32.dll\"\")] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x,int y,int cx, int xy, uint flagsw);\" -name \"Win32SetWindowPos\" -passThru )::SetWindowPos((Add-Type -memberDefinition \"[DllImport(\"\"Kernel32.dll\"\")] public static extern IntPtr GetConsoleWindow();\" -name \"Win32GetConsoleWindow\" -passThru )::GetConsoleWindow(),-1,0,0,0,0,67)"

title Ping tool
mode con: cols=50 lines=25

:PING
cls & set /p address= [*] Host to ping: 
@echo [*] Started pinging at: %time%
title Pinging %address%
if %ERRORLEVEL% == 1 echo Host didn't respond.         

ping  %address%  -t  & echo. & pause. & goto :PING

I'm trying to make it so that when I receive an errorcode (Request Timed out) that it'd print "Host didn't respond" instead of the usual. However it does not work.

Normally my ping would output this:

[*] Host to ping: 8.8.8.8
[*] Started pinging at: 13:44:29.05

Pinging 8.8.8.8 with 32 bytes of data:
Reply from 8.8.8.8: bytes=32 time=28ms TTL=52
Reply from 8.8.8.8: bytes=32 time=16ms TTL=52
Request timed out.
Request timed out.

etc.

But I want it to look like this:

[*] Host to ping: 8.8.8.8
[*] Started pinging at: 13:44:29.05

Pinging 8.8.8.8 with 32 bytes of data:
Reply from 8.8.8.8: bytes=32 time=28ms TTL=52
Reply from 8.8.8.8: bytes=32 time=16ms TTL=52
Host didn't respond.
Host didn't respond.

How would I go on doing this?

P.S the second line of the script is a command that I found here, which makes the CMD window be always on top. Very useful!

user3840170
  • 26,597
  • 4
  • 30
  • 62
Buster
  • 446
  • 5
  • 16
  • if you want the errorlevel of a command, then it doesn't make sense to check the errorlevel before the command had a chance to run. (also `/t` doesn't make sense here, because `ping` won't finish) – Stephan Mar 30 '20 at 11:31
  • I'm sorry, that's not really what I mean. I'll rephrase the question. – Buster Mar 30 '20 at 11:43
  • You could capture the ping output with a `FOR /F` command and do string replacement but you would be better off with a command that can do in line editing. There really isn't any native stream editor in Windows. Your options would be to use something like JREPL.bat which can be found on the Dostips.com forum or download Windows version of SED. – Squashman Mar 30 '20 at 13:20

2 Answers2

2

You can't intercept the output of a command while it's still running, so ping -t won't work for you. You need ping -n 1 in a loop, so you are able to react to each single ping package:

:loop
ping -n 1 www.google.com | find "TTL=" || echo Host didn't respond. 
goto :loop

Don't forget to implement some sort of "break the loop"

NOTE: this fails in your internal network, because a ping response of Reply from <localhost>: Destination host unreachable. is considered as "Success", because there was an answer (just not from the destination).

Stephan
  • 53,940
  • 10
  • 58
  • 91
1

You can redirect the output to a file, test the errorlevel, then type in the output if Errorlevel check met.

@Echo off
:ping
cls & set /p address= [*] Host to ping: 
ping %address%>output.txt
If Errorlevel 1 (Echo(Host unavailable) Else (TYPE output.txt)
pause>nul
Goto :ping
T3RR0R
  • 2,747
  • 3
  • 10
  • 25
  • Yeah but I don't want to write it to a text file, I want it to echo to the CMD – Buster Mar 30 '20 at 11:44
  • If you take the time to understand / try the exampled code, you will see that on fail ONLY the fail message Is written to console, and through the type command, a succesful ping Is displayed on the console. – T3RR0R Mar 30 '20 at 11:51