Page 1 of 1

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

Posted: 08 Nov 2013, 02:06
by just me
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

Re: Ping4 - IPv4 ping function

Posted: 10 Nov 2013, 10:49
by TLM
Nice work :D
The octet needle can be ^((|\.)\d{1,3}){4}$

Re: Ping4 - IPv4 ping function

Posted: 01 Dec 2013, 11:14
by Joe Glines
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

Re: Ping4 - IPv4 ping function

Posted: 01 Dec 2013, 15:25
by just me
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.

Re: Ping4 - IPv4 ping function

Posted: 01 Dec 2013, 15:53
by Joe Glines
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

Re: Ping4 - IPv4 ping function

Posted: 01 Dec 2013, 16:17
by SKAN
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.

Re: Ping4 - IPv4 ping function

Posted: 01 Dec 2013, 16:24
by Joe Glines
Sweet! Looks like Xmas arrived early! I'm always amazed at the knowledge of y'all on the forums! It is quite humbling! :D

Re: Ping4 - IPv4 ping function

Posted: 15 Jul 2015, 06:17
by jNizM
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)

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

Posted: 16 Jul 2015, 02:35
by just me
Hmmm, seems that the Iphlpapi.dll has to be loaded explicitly (again).
Fixed!

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

Posted: 11 Oct 2016, 08:19
by Elesar
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.

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

Posted: 13 Oct 2016, 01:58
by just me

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.

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

Posted: 28 Oct 2016, 01:34
by nahusa
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.

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

Posted: 06 Nov 2016, 03:27
by just me
No.

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

Posted: 26 Aug 2017, 23:31
by tmplinshi
Thanks!

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

Posted: 20 May 2020, 05:51
by hasantr
What is the way to quickly scan devices on my network. It was very slow I tried.