While some people like to mock newbies instead of helping them, others still remember how it feels like. Besides, it's annoying having to deal with a DOS command window when calling the built-in ping.exe in Win9x. Maybe someone will find this function useful.
Main function to call is
Ping(); the others are helpers but may be used independently, if needed.
Changelog:
Code:
*** v2.0 changes the function name, as requested by tuncay down this topic
EDIT May 29, 2009
v1.1
The function code has been cleaned up a little by removing the example. Also a few comments have been added.
Another example, in form of a ready-to-use script, has been provided separately.
Example has been updated at 18:36 EEST.
v1.2
Added speech capabilities thanks to the script provided at http://www.autohotkey.com/forum/viewtopic.php?p=229945#229945 (thank you, DerRaphael).
It requires the COM library, downloadable at http://www.autohotkey.com/forum/viewtopic.php?t=22923 (thank you, Sean).
/EDIT
June 13, 2009
v1.5.1
- Added settings saving through ini file
- Added translation option
July 7, 2009
-Fixed small typo in main function script (ErroLevel -> ErrorLevel)
April 29, 2010
v2.0
• As per Tuncay's request (see the forum topic), the names of all functions have been changed for better stdlib compatibility. Main function - formerly A_Ping() - is now called ping(); script's name has been changed accordingly, version was raised to 2.0. The NetCon Alert script has also been modified to reflect the aforementioned changes and its version was also boosted to 2.0 (for consistency with the function version).
July 14, 2010 v2.1.0
• added round trip display, on request
• minor change to the _T(string) function
September 5, 2010
• Changed script date (thanks Tuncay for the heads up)
The ping() function is unchanged; only the NetCon Alert example script was modified, as mentioned above.
Download page for NetCon Alert (includes ping() function and older versions):
NetCon Alert download pageCOMPATIBILITY: AutoHotkey 1.0.48.05 (AHK Basic)==============
Feel free to modify any of them if they don't work in your super-duper OS - it's been built and tested in Win98SE only.
NetCon Alert example:Code:
; NetCon Alert by Drugwash, January 1, 2010
version=2.1.0
;***********************************************
#Persistent
#NoEnv
#SingleInstance, force
SetBatchLines, -1
DetectHiddenWindows, On
SetWorkingDir %A_ScriptDir%
p = %1%
debug := RegExMatch(p, "i)d[e]b[u]g")
inifile := "NCA_settings.ini"
IfNotExist, %inifile%
{
spk=0 ; speech activation switch
isit=0 ; speech limit switch
times=1 ; speech count
spoken=0 ; spoken count
hostlist=127.0.0.1|192.168.2.1|www.google.com||www.wikipedia.com|99.99.99.99|
;host := "www.google.com" ; address to ping (preselected in the ComboBox)
data=AHK test ; data to be sent on ping
timeout=500 ; ping timeout [ms]
itime=5000 ; initial ping loop time [ms]
stime=1000 ; secondary ping time [ms]
pause=0 ; pause checking switch
fail=0 ; failure count
chk=0 ; failed checks count (per host)
max = 3 ; no. of failures that yield alert
time := itime ; set timer to ping loop time
lang=EN ; default language
}
else
{
IniRead, spk, %inifile%, Settings, UseSpeech, 0
IniRead, isit, %inifile%, Settings, LimitSpeech, 0
IniRead, times, %inifile%, Settings, SpeechLimitTimes, 1
IniRead, itime, %inifile%, Settings, PrimaryPingDelay, 5000
IniRead, stime, %inifile%, Settings, SecondaryPingDelay, 1000
IniRead, max, %inifile%, Settings, Failures, 3
IniRead, hostlist, %inifile%, Hosts, HostList, 127.0.0.1|192.168.2.1|www.google.com||www.wikipedia.com|99.99.99.99|
IniRead, data, %inifile%, Ping, Data, AHK test
IniRead, timeout, %inifile%, Ping, Timeout, 500
IniRead, lang, %inifile%, Translation, Language, EN
}
end := InStr(hostlist, "||")-1
Loop
if (A_Index = end || SubStr(hostlist, end - A_Index, 1) = "|")
{
begin := end - A_Index + 1
end := end - begin + 1
break
}
host := SubStr(hostlist, begin, end)
langtmpl := ".\lang\NCA_lang_EN.ini"
langfile := ".\lang\NCA_lang_" lang ".ini"
lang := (lang) ? lang : "EN"
mtitle := "NetCon Alert " version ; main window title
stitle := "NCA Settings" ; settings window title
;***********************************************
if !A_IsCompiled
Menu, Tray, Icon, NCA.ico
Menu, Tray, NoStandard
Menu, Tray, Add, Show notification, showit
Menu, Tray, Add, Settings, setit
Menu, Tray, Add, Pause pinging, pauseit
Menu, Tray, Add, Exit, quitit
Menu, Tray, Default, Show notification
if debug
Menu, Tray, Add, Reload, reloadit
;***********************************************
Gui, Margin, 10, 10
Gui, Add, Groupbox, xm ym-5 w310 h100 Center, Notification
Gui, Add, Checkbox, xp y+13 w110 vbugger, Don't show again
Gui, Font, s18 cRed bold, Tahoma
Gui, Add, Text, xm+5 ym+10 w300 h30 Center +0x200, Network OK !
Gui, Font
Gui, Add, Text, xp y+5 w300 h14 Center +0x200, No ping to %host% failed so far.
Gui, Add, Text, xp y+1 w300 h14 Center +0x200, Network connection is up and running.
Gui, Add, Text, xp y+1 w300 h14 Center +0x200,
Gui, Add, Button, x120 y+20 w80 h30 Default, OK
Gui, Add, Button, x+60 yp+3 w60 h24 +0x8000, Settings ; BS_FLAT style
Gui, Show, Hide, %mtitle%
;***********************************************
Gui, 2:Margin, 5, 5
Gui, 2:Add, Groupbox, xm ym-5 w160 h140, Ping
Gui, 2:Add, Text,xm+5 yp+15, Host name or address:
Gui, 2:Add, ComboBox, xp y+2 w150 r7 Sort vhostlist, %hostlist%
Gui, 2:Add, Text, xp y+5, Data to be sent with PING:
Gui, 2:Add, Edit, xp y+2 w150 -Multi Limit vdata, %data%
Gui, 2:Add, Text, xp y+5 w70, Timeout:
Gui, 2:Add, Edit, xp y+2 w30-Multi Limit Number vtimeout, %timeout%
Gui, 2:Add, Text, x+5 yp w30 h20 +0x200, ms.
Gui, 2:Add, Button, x+5 yp-2 w80 h24 +0x8000, Remove host ; BS_FLAT style
Gui, 2:Add, Groupbox, xm y+10 w160 h60, Speech
Gui, 2:Add, Checkbox, xm+5 yp+15 w150 vts gtspeech, Speak when ping fails
Gui, 2:Add, Checkbox, xp+14 y+7 Disabled vdeaf gisenough, Only speak
Gui, 2:Add, Edit, x+2 yp-3 w30 Limit2 Number -Multi Disabled venough ghowmuch, %times%
Gui, 2:Add, UpDown, vtimes Range1-999, %times%
Gui, 2:Add, Text, x+3 yp+3 w30 Disabled, time
Gui, 2:Add, Button, xm y+20 w54 h24 Default, OK
Gui, 2:Add, Button, x+46 yp w60 h24, Cancel
Gui, 2:Add, DDL, xm+56 yp+2 w40 h20 r10 vlng,
GuiControl,2:, Button4, %spk%
if spk
GuiControl, 2:Enable, Button5
GuiControl,2:, Button5, %isit%
if isit && spk
{
GuiControl, 2:Enable, Edit4
GuiControl, 2:Enable, Static5
}
Gui, 2:Show, Hide, %stitle%
Gui, 2:Submit
WinGet, controlsD, ControlList, %mtitle%
WinGet, controlsS, ControlList, %stitle%
gosub lang
Loop, .\lang\NCA_lang_??.ini
langall := (langall) ? langall "|" SubStr(A_LoopFileName, 10,2) : SubStr(A_LoopFileName, 10,2)
GuiControl, 2:, ComboBox2, %langall%
GuiControl, 2:ChooseString, ComboBox2, %lang%
;***********************************************
host := hostlist
fail=1 ; helps initializing display info after first ping
SetTimer, chknet, %itime%
return
;***********************************************
; ping timer subroutine
chknet:
res := ping(host, data, timeout) ; ping the selected host
rt := NumGet(res+0, 8, "UInt") ; get reply time [ms]
if SubStr(res, 1, 5) = "Error" ; check for reply error
{
if !fail
SetTimer, chknet, %stime% ; shorten the ping loop time
fail++ ; count subsequent failures
if (fail = max)
{
fail=0
SetTimer, chknet, %itime%
chk++
gc := chk=1 ? "" : "s"
GuiControl,, Static1, % _T(not1f)
GuiControl,, Static2, % _T(not2f)
GuiControl,, Static3, % _T(not3f)
GuiControl,, Static4, % _T(not6f)
if !bugger
Gui, Show
if spk
gosub speakit
}
}
else
if fail
goto resetit
else
GuiControl,1:, Static4, % _T(not6)
return
resetit:
fail = 0 ; reset failure count
SetTimer, chknet, %itime% ; reset ping loop time
GuiControl,1:, Static1, % _T(not1)
GuiControl,1:, Static2, % _T(not2)
GuiControl,1:, Static3, % _T(not3)
GuiControl,1:, Static4, % _T(not6)
return
ButtonOK:
GuiEscape:
GuiClose:
Gui, Submit
return
ButtonSettings:
setit:
if !pause
gosub pauseit ; pause the script while changing settings
Gui, 2:Show
ControlGet, hlc, List,, ComboBox1, %stitle%
ControlGetText, olddata, Edit2, %stitle%
ControlGetText, oldtout, Edit3, %stitle%
ControlGet, oldspeech, Checked,, Button4, %stitle%
ControlGet, olddeaf, Checked,, Button5, %stitle%
ControlGetText, oldenough, Edit4, %stitle%
ControlGetText, oldtimes, Static5, %stitle%
ControlGet, oldlang, Choice,, ComboBox2, %stitle%
return
2ButtonRemovehost:
Gui, 2:Submit, NoHide
ControlGet, hlct, List,, ComboBox1 , %stitle% ; get the list of host
ControlGetText, badhost, Edit1, %stitle% ; get selected host
pos := InStr(hlct, badhost, false, 1) ; check if selected host belongs to the list
if pos
{
if pos = 1
hlct := SubStr(hlct, pos+StrLen(badhost)+1)
else if (pos+StrLen(badhost) = StrLen(hlct))
hlct := SubStr(hlct, 1, pos-1)
else
hlct := SubStr(hlct, 1, pos-1) SubStr(hlct, pos+StrLen(badhost)+1)
StringReplace, hlct, hlct, `n, |, All
StringReplace, hlct, hlct, |, ||
GuiControl, 2:, ComboBox1, |%hlct%
Gui, 2:Submit, NoHide
}
return
2ButtonOK: ; save settings
Gui, 2:Submit,NoHide
host := hostlist ? hostlist : "www.google.com"
data := data ? data : "AHK test"
timeout := timeout ? timeout : "500"
ControlGet, hlc, List,, ComboBox1, %stitle%
IfNotInString, hlc, %host%
GuiControl, 2:, ComboBox1, %host%||
Gui, 2:Submit, NoHide
chk=0 ; reset failure count per host
fail=1 ; this helps in resetting display info
spoken=0 ; reset speech count per host
lang := lng
ControlGet, hlc, List,, ComboBox1, %stitle%
StringReplace, hlc, hlc, `n, |, All
StringReplace, hlc, hlc, %host%, %host%|
IniWrite, %spk%, %inifile%, Settings, UseSpeech
IniWrite, %isit%, %inifile%, Settings, LimitSpeech
IniWrite, %times%, %inifile%, Settings, SpeechLimitTimes
IniWrite, %itime%, %inifile%, Settings, PrimaryPingDelay
IniWrite, %stime%, %inifile%, Settings, SecondaryPingDelay
IniWrite, %max%, %inifile%, Settings, Failures
IniWrite, %hlc%, %inifile%, Hosts, HostList
IniWrite, %data%, %inifile%, Ping, Data
IniWrite, %timeout%, %inifile%, Ping, Timeout
IniWrite, %lang%, %inifile%, Translation, Language
Gui, 2:Hide
GuiControl,1:, Static1, % _T(not4)
GuiControl,1:, Static2, % _T(not5)
GuiControl,1:, Static3,
goto pauseit
2ButtonCancel: ; (cancel any changes and) close the settings panel
2GuiEscape:
2GuiClose:
if hlct
GuiControl, 2:, ComboBox1, |%hlc%
hlct=
GuiControl, 2:ChooseString, ComboBox1, %host%
GuiControl, 2:, Edit2, %olddata%
GuiControl, 2:, Edit3, %oldtout%
GuiControl, 2:, Button4, %oldspeech%
GuiControl, 2:, Button5, %olddeaf%
spk := oldspeech
isit := olddeaf
gosub common
GuiControl, 2:, enough, %oldenough%
GuiControl, 2:, times, %oldtimes%
GuiControl, 2:ChooseString, ComboBox2, %oldlang%
gosub howmuch
Gui, 2:Hide
goto pauseit
showit:
Gui, Show
return
pauseit:
Menu, Tray, ToggleCheck, Pause pinging
pause := !pause
op := pause ? "Off" : "On"
SetTimer, chknet, %op%
return
reloadit:
Reload
quitit:
if iscom
{
COM_Release(pspeaker)
COM_Term()
}
ExitApp
speakit: ; using the script from http://www.autohotkey.com/forum/viewtopic.php?p=229945#229945
if (deaf && spoken >= enough)
return
if !iscom
iscom := COM_Init()
pspeaker := COM_CreateObject("SAPI.SpVoice")
txt := spkmsg ? spkmsg : "Network failure! Please check your network connection."
COM_Invoke(pspeaker, "Speak", txt)
spoken++
return
tspeech:
spk := !spk
common:
op := spk ? "Enable" : "Disable"
GuiControl, 2:%op%, Button5
if isit & spk
{
GuiControl, 2:Enable, Edit4
GuiControl, 2:Enable, Static5
}
else
{
GuiControl, 2:Disable, Edit4
GuiControl, 2:Disable, Static5
}
return
howmuch:
ControlGetText, isenough, Edit4
GuiControl,, times, %isenough%
if lang = EN
{
timeshow := isenough != 1 ? "times" : "time"
GuiControl, 2:, Static5, %timeshow%
}
return
isenough:
isit := !isit
spoken := isit ? "0" : spoken
goto common
lang:
IfNotExist, %langtmpl%
{
Loop, Parse, controlsD, `n
{
ControlGetText, field, %A_LoopField%, %mtitle%
if A_LoopField not contains Static
IniWrite, %field%, %langtmpl%, Display, %A_LoopField%
}
Loop, Parse, controlsS, `n
{
ControlGetText, field, %A_LoopField%, %stitle%
if A_LoopField not contains ComboBox,Edit,msctls_updown32
IniWrite, %field%, %langtmpl%, Settings, %A_LoopField%
}
IniWrite, Network OK !, %langtmpl%, Notifications, NetOK
IniWrite, Network failure!, %langtmpl%, Notifications, NetFailed
IniWrite, No ping to `%host`% failed so far., %langtmpl%, Notifications, NetOKinfo
IniWrite, Pinging `%host`% failed `%chk`% time`%gc`%., %langtmpl%, Notifications, NetFailedInfo
IniWrite, Network connection is up and running., %langtmpl%, Notifications, NetOKdetails
IniWrite, Please check your network connection and/or settings below., %langtmpl%, Notifications, NetFailedDetails
IniWrite, Please wait..., %langtmpl%, Notifications, HostResetWait
IniWrite, Pinging `%host`%, %langtmpl%, Notifications, HostResetPing
IniWrite, Round trip : %rt% ms, %langtmpl%, Notifications, RoundTrip
IniWrite, Timeout >= %timeout% ms, %langtmpl%, Notifications, RoundTripFailed
IniWrite, Network failure! Please check your network connection., %langtmpl%, Notifications, SpokenMessage
}
if (lang = "EN" || !FileExist(langfile) )
langfile := langtmpl
Loop, Parse, controlsD, `n
{
IniRead, field, %langfile%, Display, %A_LoopField%, skip
if field != skip
GuiControl,1:, %A_LoopField%, % _T(field)
}
Loop, Parse, controlsS, `n
{
IniRead, field, %langfile%, Settings, %A_LoopField%, skip
if field != skip
GuiControl,2:, %A_LoopField%, %field%
}
IniRead, not1, %langfile%, Notifications, NetOK, Network OK !
IniRead, not1f, %langfile%, Notifications, NetFailed, Network failure!
IniRead, not2, %langfile%, Notifications, NetOKinfo, No ping to %host% failed so far.
IniRead, not2f, %langfile%, Notifications, NetFailedInfo, Pinging %host% failed %chk% time%gc%.
IniRead, not3, %langfile%, Notifications, NetOKdetails, Network connection is up and running.
IniRead, not3f, %langfile%, Notifications, NetFailedDetails, Please check your network connection and/or settings below.
IniRead, not4, %langfile%, Notifications, HostResetWait, Please wait...
IniRead, not5, %langfile%, Notifications, HostResetPing, Pinging %host%
IniRead, not6, %langfile%, Notifications, RoundTrip, Round trip : %rt% ms
IniRead, not6f, %langfile%, Notifications, RoundTripFailed, Timeout >= %timeout% ms
IniRead, spkmsg, %langfile%, Notifications, SpokenMessage, Network failure! Please check your network connection.
return
_T(string)
{
Global
Transform, strong, Deref, %string%
if debug
msgbox, Old string: %string%`nNew string: %strong%`nHost: %host%
return strong
}
; download "com.ahk" from http://www.autohotkey.com/forum/viewtopic.php?t=22923
;comment any of the lines below if you have the respective function in the lib folder
;#include ping.ahk
;#include COM.ahk
Ping function:Code:
; Ping function by Drugwash April 29, 2010
; v2.0
;*********************************
ping_(adr, data, timeout)
{
static reply
ErrorLevel = 0
SetFormat, IntegerFast, H
cAdr := DllCall("wsock32\inet_addr", UInt, &adr, UInt) ; convert address to 32bit UInt
if cAdr = 0xFFFFFFFF
cAdr := DllCall("ws2_32\inet_addr", str, adr, Int) ; second attempt at conversion, using ws2_32
if cAdr = 0xFFFFFFFF
{
ErrorLevel = 1
return err := "Error: Cannot convert address to UInt."
}
; test for function presence since it's located in different libs through various OS
hLib := DllCall("LoadLibrary", str, "iphlpapi.dll")
if hLib
{
hPrAdr := DllCall("GetProcAddress", UInt, hLib, str, "IcmpCreateFile")
if hPrAdr
; hPort := DllCall("iphlpapi\IcmpCreateFile", UInt) ; open a port (iphlpapi.dll in XP+)
hPort := DllCall(hPrAdr, UInt) ; open a port (iphlpapi.dll in XP+)
else
DllCall("FreeLibrary", UInt, hLib)
}
if !hPort
hPort := DllCall("icmp\IcmpCreateFile", UInt) ; open a port (icmp.dll in Win2000 and lower)
if !hPort
{
ErrorLevel = 1
return err := "Error: Cannot open port."
}
SetFormat, Integer, D
szreply = 278 ; ICMP_ECHO_REPLY structure
VarSetCapacity(reply, szreply, 0)
DllCall("icmp\IcmpSendEcho", UInt, hPort, UInt, cAdr, UInt, &data, UInt, StrLen(data), UInt, NULL, UInt, &reply, UInt, szreply, UInt, timeout, UInt)
errcode := NumGet(reply, 4, "UInt") ; check for status
errcode := errcode <> 0 ? errcode : errcode+11000
if errcode = 11001 ; function returned 'buffer too small' so we increase it and try again
{
VarSetCapacity(reply, NumGet(reply, 12, "UShort")+16)
DllCall("icmp\IcmpSendEcho", UInt, hPort, UInt, cAdr, UInt, &data, UInt, StrLen(data), UInt, NULL, UInt, &reply, UInt, szreply, UInt, timeout, UInt)
errcode := NumGet(reply, 4, "UInt") ; another check for status on 2-nd attempt
errcode := errcode <> 0 ? errcode : errcode+11000
}
err := ping_GetError(errcode, "IcmpSendEcho") ; error handling
DllCall("icmp\IcmpCloseHandle", UInt, hPort) ; close port
if errcode != 11000 ; IP_SUCCESS
{
ErrorLevel = 1
return err
}
else
; on success returns ICMP_ECHO_REPLY structure address for external processing of data
return err := &reply
}
;*********************************
ping_GetError(code, func="[ukn]") ; error translation
{
str := "Success|Reply buffer too small|Destination network unreachable|Destination host unreachable|Destination protocol unreachable|Destination port unreachable|Insufficient IP resources|Bad IP option specified|Hardware error|Packet too big|Request timed out|Bad request|Bad route|TTL expired in transit|TTL expired during fragment reassembly|Parameter problem|Datagrams are arriving too fast to be processed and datagrams may have been discarded|IP option too big|Bad destination|General failure (possible malformed ICMP packets)"
Loop, Parse, str, |
{
if (code = 11000 + A_Index - 1) || (A_Index = 20 && code = 11050)
return err := "Error " code " [" A_LoopField "] in function " func
}
return err := "Function " func " returned " code
}
;*********************************
ping_Host2IP(name)
{
ErrorLevel = 0
type := SubStr(name, 1, 1)
if type is alpha
{
hostent := DllCall("ws2_32\gethostbyname", UInt, &name, UInt) ; http://msdn.microsoft.com/en-us/library/ms738524(VS.85).aspx
if !hostent
{
err := DllCall("ws2_32\WSAGetLastError")
ErrorLevel = 1
return err
}
; string containing protocol types (mainly for debug purposes)
str := "local to host (pipes, portals)|internetwork: UDP, TCP, etc.|arpanet imp addresses|pup protocols: e.g. BSP|mit CHAOS protocols|XEROX NS protocols or IPX protocols: IPX, SPX, etc.|ISO protocols or OSI is ISO|european computer manufacturers|datakit protocols|CCITT protocols, X.25 etc|IBM SNA|DECnet|Direct data link interface|LAT|NSC Hyperchannel|AppleTalk|NetBios-style addresses|VoiceView|Protocols from Firefox|Unknown - Somebody is using this!|Banyan|Native ATM Services|Internetwork Version 6|Microsoft Wolfpack|IEEE 1284.4 WG AF"
ptrName := NumGet(hostent+0, 0, "UInt")
pt := NumGet(hostent+0, 8, "UShort")
Loop, Parse, str, |
if (A_Index = pt)
type := A_LoopField
len := NumGet(hostent+0, 10, "UShort")
ptrAddress := NumGet(hostent+0, 12, "UInt")
ptrIPAddress := NumGet(ptrAddress+0, 0, "UInt")
strAddress := NumGet(ptrIPAddress+0, 0, "UInt")
VarSetCapacity(adr, 16, 32)
DllCall("lstrcpy", UInt, &adr, UInt, DllCall("ws2_32\inet_ntoa", UInt, strAddress))
VarSetCapacity(adr, -1)
VarSetCapacity(pname, 260, 32)
DllCall("lstrcpy", UInt, &pname, UInt, ptrName)
VarSetCapacity(pname, -1)
return adr
}
else
return name
}
;*********************************
ping_DW2IP(adr)
{
res := NumGet(adr+0, 0, "Uchar") "." NumGet(adr+0, 1, "Uchar") "." NumGet(adr+0, 2, "Uchar") "." NumGet(adr+0, 3, "Uchar")
return res
}
;*********************************
ping(addr, data="AHK ping test", timeout="500")
{
; Sockets initialization http://msdn.microsoft.com/en-us/library/ms741563(VS.85).aspx
VarSetCapacity(WSADATA, 12+257+129, 0) ; WSADATA structure initialization
err := DllCall("wsock32\WSAStartup", Short, 0x101, UInt, &WSADATA, UInt)
if err > 0
{
ErrorLevel = 1
err = Socket initialization error %err% ; Failed to initialize sockets
goto error
}
address := ping_Host2IP(addr) ; address conversion to DWORD
err := ping_GetError(address, "ping_Host2IP") ; error handling
if ErrorLevel
goto error
err := ping_(address, data, timeout) ; ping function call
error:
EL := ErrorLevel
DllCall("wsock32\WSACleanup") ; Sockets cleanup & close
ErrorLevel := EL
return err
}