Ping4 - IPv4 ping function (2015-07-16)

Post your working scripts, libraries and tools
just me
Posts: 5837
Joined: 02 Oct 2013, 08:51
Location: Germany

Ping4 - IPv4 ping function (2015-07-16)

08 Nov 2013, 02:06

Just a variation of the Ping() function included in Uberi's SimplePing with added name resolution:

Update on 2015-07-16:
  • fixed bug on Win 8.

Code: Select all

; ======================================================================================================================
; Function:       IPv4 ping with name resolution, based upon 'SimplePing' by Uberi ->
;                 http://www.autohotkey.com/board/topic/87742-simpleping-successor-of-ping/
; Parameters:     Addr     -  IPv4 address or host / domain name.
;                 ----------  Optional:
;                 Result   -  Object to receive the result in three keys:
;                             -  InAddr - Original value passed in parameter Addr.
;                             -  IPAddr - The replying IPv4 address.
;                             -  RTTime - The round trip time, in milliseconds.
;                 Timeout  -  The time, in milliseconds, to wait for replies.
; Return values:  On success: The round trip time, in milliseconds.
;                 On failure: "", ErrorLevel contains additional informations.
; Tested with:    AHK 1.1.22.03
; Tested on:      Win 8.1 x64
; Authors:        Uberi / just me
; Change log:     1.0.01.00/2015-07-16/just me - fixed bug on Win 8
;                 1.0.00.00/2013-11-06/just me - initial release
; MSDN:           Winsock Functions   -> http://msdn.microsoft.com/en-us/library/ms741394(v=vs.85).aspx
;                 IP Helper Functions -> hhttp://msdn.microsoft.com/en-us/library/aa366071(v=vs.85).aspx
; ======================================================================================================================
Ping4(Addr, ByRef Result := "", Timeout := 1024) {
   ; ICMP status codes -> http://msdn.microsoft.com/en-us/library/aa366053(v=vs.85).aspx
   ; WSA error codes   -> http://msdn.microsoft.com/en-us/library/ms740668(v=vs.85).aspx
   Static WSADATAsize := (2 * 2) + 257 + 129 + (2 * 2) + (A_PtrSize - 2) + A_PtrSize
   OrgAddr := Addr
   Result := ""
   ; -------------------------------------------------------------------------------------------------------------------
   ; Initiate the use of the Winsock 2 DLL
   VarSetCapacity(WSADATA, WSADATAsize, 0)
   If (Err := DllCall("Ws2_32.dll\WSAStartup", "UShort", 0x0202, "Ptr", &WSADATA, "Int")) {
      ErrorLevel := "WSAStartup failed with error " . Err
      Return ""
   }
   If !RegExMatch(Addr, "^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$") { ; Addr contains a name
      If !(HOSTENT := DllCall("Ws2_32.dll\gethostbyname", "AStr", Addr, "UPtr")) {
         DllCall("Ws2_32.dll\WSACleanup") ; Terminate the use of the Winsock 2 DLL
         ErrorLevel := "gethostbyname failed with error " . DllCall("Ws2_32.dll\WSAGetLastError", "Int")
         Return ""
      }
      PAddrList := NumGet(HOSTENT + 0, (2 * A_PtrSize) + 4 + (A_PtrSize - 4), "UPtr")
      PIPAddr   := NumGet(PAddrList + 0, 0, "UPtr")
      Addr := StrGet(DllCall("Ws2_32.dll\inet_ntoa", "UInt", NumGet(PIPAddr + 0, 0, "UInt"), "UPtr"), "CP0")
   }
   INADDR := DllCall("Ws2_32.dll\inet_addr", "AStr", Addr, "UInt") ; convert address to 32-bit UInt
   If (INADDR = 0xFFFFFFFF) {
      ErrorLevel := "inet_addr failed for address " . Addr
      Return ""
   }
   ; Terminate the use of the Winsock 2 DLL
   DllCall("Ws2_32.dll\WSACleanup")
   ; -------------------------------------------------------------------------------------------------------------------
   HMOD := DllCall("LoadLibrary", "Str", "Iphlpapi.dll", "UPtr")
   Err := ""
   If (HPORT := DllCall("Iphlpapi.dll\IcmpCreateFile", "UPtr")) { ; open a port
      REPLYsize := 32 + 8
      VarSetCapacity(REPLY, REPLYsize, 0)
      If DllCall("Iphlpapi.dll\IcmpSendEcho", "Ptr", HPORT, "UInt", INADDR, "Ptr", 0, "UShort", 0
                                            , "Ptr", 0, "Ptr", &REPLY, "UInt", REPLYsize, "UInt", Timeout, "UInt") {
         Result := {}
         Result.InAddr := OrgAddr
         Result.IPAddr := StrGet(DllCall("Ws2_32.dll\inet_ntoa", "UInt", NumGet(Reply, 0, "UInt"), "UPtr"), "CP0")
         Result.RTTime := NumGet(Reply, 8, "UInt")
      }
      Else
         Err := "IcmpSendEcho failed with error " . A_LastError
      DllCall("Iphlpapi.dll\IcmpCloseHandle", "Ptr", HPORT)
   }
   Else
      Err := "IcmpCreateFile failed to open a port!"
   DllCall("FreeLibrary", "Ptr", HMOD)
   ; -------------------------------------------------------------------------------------------------------------------
   If (Err) {
      ErrorLevel := Err
      Return ""
   }
   ErrorLevel := 0
   Return Result.RTTime
}

Code: Select all

#NoEnv
SetBatchLines, -1
RTT := Ping4("www.ahkscript.org", Result)
If (ErrorLevel)
   MsgBox, 16, Ping4, Error:`r`n%ErrorLevel%
Else
   MsgBox, 0, Ping4, % "InAddr:`t" . Result.INAddr . "`r`n"
                     . "IPAddr:`t" . Result.IPAddr . "`r`n"
                     . "RTTime:`t" . Result.RTTime . "`r`n"
                     . "RetVal:`t" . RTT
ExitApp
#Include Ping4.ahk
Last edited by just me on 16 Jul 2015, 02:30, edited 1 time in total.
User avatar
TLM
Posts: 1415
Joined: 01 Oct 2013, 07:52
GitHub: TLMcode
Contact:

Re: Ping4 - IPv4 ping function

10 Nov 2013, 10:49

Nice work :D
The octet needle can be ^((|\.)\d{1,3}){4}$
for direct help, tweet at me: https://twitter.com/CW_DTech
User avatar
Joe Glines
Posts: 576
Joined: 30 Sep 2013, 20:49
Facebook: https://www.facebook.com/theAutomatorGuru/
Google: https://plus.google.com/105328929654286634910
GitHub: joetazz
Location: Dallas
Contact:

Re: Ping4 - IPv4 ping function

01 Dec 2013, 11:14

is it possible to adapt this to use the IP address and bring back the domain/URL (or even better the name of the OrgName as shown on this site: http://whoisthisip.com/ipwhois/74.125.45.100
just me
Posts: 5837
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Ping4 - IPv4 ping function

01 Dec 2013, 15:25

Hmmm, you might try this one:

Code: Select all

#NoEnv
SetBatchLines, -1
RTT := Ping4("www.ahkscript.org", Result)
If (ErrorLevel)
   MsgBox, 16, Ping4, Error:`r`n%ErrorLevel%
Else
   MsgBox, 0, Ping4, % "InAddr:`t" . Result.INAddr . "`r`n"
                     . "IPAddr:`t" . Result.IPAddr . "`r`n"
                     . "RTTime:`t" . Result.RTTime . "`r`n"
                     . "Name:`t"   . Result.Name   . "`r`n"
                     . "RetVal:`t" . RTT
RTT := Ping4("www.google.com", Result)
If (ErrorLevel)
   MsgBox, 16, Ping4, Error:`r`n%ErrorLevel%
Else
   MsgBox, 0, Ping4, % "InAddr:`t" . Result.INAddr . "`r`n"
                     . "IPAddr:`t" . Result.IPAddr . "`r`n"
                     . "RTTime:`t" . Result.RTTime . "`r`n"
                     . "Name:`t"   . Result.Name   . "`r`n"
                     . "RetVal:`t" . RTT
ExitApp

; ======================================================================================================================
; Function:       IPv4 ping with name resolution, based upon 'SimplePing' by Uberi ->
;                 http://www.autohotkey.com/board/topic/87742-simpleping-successor-of-ping/
; Parameters:     Addr     -  IPv4 address or host / domain name.
;                 ----------  Optional:
;                 Result   -  Object to receive the result in three keys:
;                             -  InAddr - Original value passed in parameter Addr.
;                             -  IPAddr - The replying IPv4 address.
;                             -  Name   - The replying host name.
;                             -  RTTime - The round trip time, in milliseconds.
;                 Timeout  -  The time, in milliseconds, to wait for replies.
; Return values:  On success: The round trip time, in milliseconds.
;                 On failure: "", ErrorLevel contains additional informations.
; AHK version:    AHK 1.1.13.01
; Tested on:      Win XP - AHK A32/U32, Win 7 x64 - AHK A32/U32/U64
; Authors:        Uberi / just me
; Version:        1.0.00.00/2013-11-06/just me - initial release
;                 1.0.01.00/2013-12-01/just me - added return of host name
; MSDN:           Winsock Functions   -> http://msdn.microsoft.com/en-us/library/ms741394(v=vs.85).aspx
;                 IP Helper Functions -> hhttp://msdn.microsoft.com/en-us/library/aa366071(v=vs.85).aspx
; ======================================================================================================================
Ping4(Addr, ByRef Result := "", Timeout := 1024) {
   ; ICMP status codes -> http://msdn.microsoft.com/en-us/library/aa366053(v=vs.85).aspx
   ; WSA error codes   -> http://msdn.microsoft.com/en-us/library/ms740668(v=vs.85).aspx
   Static WSADATAsize := (2 * 2) + 257 + 129 + (2 * 2) + (A_PtrSize - 2) + A_PtrSize
   OrgAddr := Addr
   Result := ""
   ; -------------------------------------------------------------------------------------------------------------------
   ; Initiate the use of the Winsock 2 DLL
   VarSetCapacity(WSADATA, WSADATAsize, 0)
   If (Err := DllCall("Ws2_32.dll\WSAStartup", "UShort", 0x0202, "Ptr", &WSADATA, "Int")) {
      ErrorLevel := "WSAStartup failed with error " . Err
      Return ""
   }
   If !RegExMatch(Addr, "^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$") { ; Addr contains a name
      If !(HOSTENT := DllCall("Ws2_32.dll\gethostbyname", "AStr", Addr, "UPtr")) {
         DllCall("Ws2_32.dll\WSACleanup") ; Terminate the use of the Winsock 2 DLL
         ErrorLevel := "gethostbyname failed with error " . DllCall("Ws2_32.dll\WSAGetLastError", "Int")
         Return ""
      }
      PAddrList := NumGet(HOSTENT + 0, (2 * A_PtrSize) + 4 + (A_PtrSize - 4), "UPtr")
      PIPAddr   := NumGet(PAddrList + 0, 0, "UPtr")
      Addr := StrGet(DllCall("Ws2_32.dll\inet_ntoa", "UInt", NumGet(PIPAddr + 0, 0, "UInt"), "UPtr"), "CP0")
   }
   INADDR := DllCall("Ws2_32.dll\inet_addr", "AStr", Addr, "UInt") ; convert address to 32-bit UInt
   If (INADDR = 0xFFFFFFFF) {
      ErrorLevel := "inet_addr failed for address " . Addr
      DllCall("Ws2_32.dll\WSACleanup")
      Return ""
   }
   ; -------------------------------------------------------------------------------------------------------------------
   Err := ""
   If (HPORT := DllCall("Iphlpapi.dll\IcmpCreateFile", "UPtr")) { ; open a port
      REPLYsize := 32 + 8
      VarSetCapacity(REPLY, REPLYsize, 0)
      If DllCall("Iphlpapi.dll\IcmpSendEcho", "Ptr", HPORT, "UInt", INADDR, "Ptr", 0, "UShort", 0
                                            , "Ptr", 0, "Ptr", &REPLY, "UInt", REPLYsize, "UInt", Timeout, "UInt") {
         Result := {}
         Result.InAddr := OrgAddr
         Result.IPAddr := StrGet(DllCall("Ws2_32.dll\inet_ntoa", "UInt", NumGet(Reply, 0, "UInt"), "UPtr"), "CP0")
         Result.RTTime := NumGet(Reply, 8, "UInt")
      }
      Else
         Err := "IcmpSendEcho failed with error " . A_LastError
      DllCall("Iphlpapi.dll\IcmpCloseHandle", "Ptr", HPORT)
   }
   Else
      Err := "IcmpCreateFile failed to open a port!"
   ; -------------------------------------------------------------------------------------------------------------------
   If (Err) {
      DllCall("Ws2_32.dll\WSACleanup")
      ErrorLevel := Err
      Return ""
   }
   VarSetCapacity(INADDR, 4, 0)
   NumPut(DllCall("Ws2_32.dll\inet_addr", "AStr", Result.IPAddr, "UInt"), INADDR, 0, "UInt")
   If (HOSTENT := DllCall("Ws2_32.dll\gethostbyaddr", "Ptr", &INADDR, "Int", 4, "Int", 2, "UPtr"))
      Result.Name := StrGet(NumGet(HOSTENT + 0, 0, "UPtr"), 256, "CP0")
   Else
      Result.Name := ""
   DllCall("Ws2_32.dll\WSACleanup")
   ErrorLevel := 0
   Return Result.RTTime
}
But I'm not sure whether it returns what you want to get.
User avatar
Joe Glines
Posts: 576
Joined: 30 Sep 2013, 20:49
Facebook: https://www.facebook.com/theAutomatorGuru/
Google: https://plus.google.com/105328929654286634910
GitHub: joetazz
Location: Dallas
Contact:

Re: Ping4 - IPv4 ping function

01 Dec 2013, 15:53

I work in email marketing at a large B2B company and use a service that provides us with the IP address of the person checking their email. While we have "company name" of our customers, it is not standardized. (thus people working for Ford Motor Company might be stored as "Ford, "Ford Motor co.","Ford Motor Company", "Ford M co." etc. I was thinking it would be really helpful if I could use the ip address to roll it up to a given company/Domain.

People using free accounts (or working from home) will still be "noise" but, overall, it could be very very helpful for the bulk of our contacts. Thus I'd like to be able to provide the IP address and have the script tell me either the domain or a Org name. The adaptation just provided above does return something but I don't think it is going to work for this goal. I GREATLY appreciate any help! I'd take a stab at it but this is way over my head!
Regards,
Joe
User avatar
SKAN
Posts: 360
Joined: 29 Sep 2013, 16:58

Re: Ping4 - IPv4 ping function

01 Dec 2013, 16:17

Joe, you may use one of the many online services.
The following snippet uses http://ip-api.com/docs/api:newline_separated
( ip-api.com is free only for non-commercial use )

Code: Select all

#NoEnv
SetWorkingDir %A_ScriptDir%

URLDownloadToFile, http://ip-api.com/line/74.125.45.100, ip-api.txt
FileRead, Text, ip-api.txt
Msgbox % Text
FileReadLine, ASN, ip-api.txt, 13
MsgBox % ASN
@ just me: PM me, or use report button if you want to split the last few posts.
User avatar
Joe Glines
Posts: 576
Joined: 30 Sep 2013, 20:49
Facebook: https://www.facebook.com/theAutomatorGuru/
Google: https://plus.google.com/105328929654286634910
GitHub: joetazz
Location: Dallas
Contact:

Re: Ping4 - IPv4 ping function

01 Dec 2013, 16:24

Sweet! Looks like Xmas arrived early! I'm always amazed at the knowledge of y'all on the forums! It is quite humbling! :D
User avatar
jNizM
Posts: 2352
Joined: 30 Sep 2013, 01:33
GitHub: jNizM
Contact:

Re: Ping4 - IPv4 ping function

15 Jul 2015, 06:17

hey just me,

tested your function with AutoHotkey v1.1.22.03 - x64 under Windows 8.1 - x64 and it crashes (hat sich aufgehängt - es passiert nichts - kann es nur über den Taskmanager killen)
[AHK] 1.1.30.01 x64 Unicode | [WIN] 10 Pro (Version 1803) x64 | [GitHub] Profile
Donations are appreciated if I could help you
just me
Posts: 5837
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Ping4 - IPv4 ping function (2015-07-16)

16 Jul 2015, 02:35

Hmmm, seems that the Iphlpapi.dll has to be loaded explicitly (again).
Fixed!
Elesar
Posts: 69
Joined: 31 Oct 2013, 07:56

Re: Ping4 - IPv4 ping function (2015-07-16)

11 Oct 2016, 08:19

I'm using this function in my Host Monitor script (https://github.com/DThomas44/Host-Monitor), and we are noticing that there are issues with name resolution compared to just doing ping or nslookup in the console, and several hosts will randomly give a bad return even if we have a running ping -t against the host that shows no issue.

Any ideas on how to improve the reliability of the function? I would really like to use it as it is much faster than the comspec implementation I had before jNizM suggested this function.
just me
Posts: 5837
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Ping4 - IPv4 ping function (2015-07-16)

13 Oct 2016, 01:58

Code: Select all

result := Object()
if !Ping4(host, result, 2500) {
    reply := hostID . "||TIMEOUT"
} else {
    reply := hostID . "|" . result.Name . "|" . result.RTTime . "ms|" . result.IPAddr
}
I'd call it wrong usage.

If an error occurred including a timeout the function will return an empty string "" and sets ErrorLevel. So you have to check ErrorLevel to distinct timeouts from other errors.

If the function returns a number including 0, no error occurred.

if !Ping4(host, result, 2500) is true for "" as well as 0.
nahusa
Posts: 6
Joined: 26 Feb 2014, 05:45

Re: Ping4 - IPv4 ping function (2015-07-16)

28 Oct 2016, 01:34

I might have overlooked it, but is this function able to specify the buffer size of the ping in bytes? Basically, the "-l" of the standard Windows ping.exe command.
just me
Posts: 5837
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Ping4 - IPv4 ping function (2015-07-16)

06 Nov 2016, 03:27

No.

Return to “Scripts and Functions”

Who is online

Users browsing this forum: solarcode, Thoughtfu1Tux and 32 guests