Функция VB (VBA) определения IP адреса по имени хоста

Самый простой способ получить IP-адрес машины, зная имя хоста, - применить функцию ResolveAddress:

Function ResolveAddress(ByVal ComputerName$) As String
    ' выполняет ICMP запрос (ping) до адреса ComputerName
    ' возвращает IP-адрес ComputerName$
    Dim oPingResult As Variant: On Error Resume Next
    For Each oPingResult In GetObject("winmgmts://./root/cimv2").ExecQuery _
        ("SELECT * FROM Win32_PingStatus WHERE Address = '" & ComputerName & "'")
        If IsObject(oPingResult) Then ResolveAddress = oPingResult.ProtocolAddress
    Next
End Function

Использовать функцию можно так:
Sub ПримерИспользованияResolveAddress()
    Debug.Print ResolveAddress("yandex.ru")    '  возвращает 87.250.250.11
    Debug.Print ResolveAddress("google.com")    '  возвращает 209.85.143.99
End Sub

Этот код (c функцией ResolveAddress) работает очень быстро (в отличие от приведённого ниже)


Кроме того, для определения имени машины, зная ее IP-адрес, а также для получения IP-адреса машины, зная ее доменное имя, можно использовать WinAPI:
Public Const PING_TIMEOUT As Long = 555, IP_SUCCESS As Long = 0, WS_VERSION_REQD As Long = &H101
Public Const INADDR_NONE As Long = &HFFFFFFFF, MAX_WSADescription As Long = 256, MAX_WSASYSStatus As Long = 128
Public Const SOCKET_ERROR = -1, AF_INET = 2, PF_INET = AF_INET, MAXGETHOSTSTRUCT = 1024, SOCK_STREAM = 1, MSG_PEEK = 2
 
Public Type ICMP_OPTIONS: Ttl As Byte: Tos As Byte: Flags As Byte: OptionsSize As Byte: OptionsData As Long: End Type
Public Type WSAData
    wVersion As Integer: wHighVersion As Integer:
    szDescription(0 To MAX_WSADescription) As Byte: szSystemStatus(0 To MAX_WSASYSStatus) As Byte:
    wMaxSockets As Long: wMaxUDPDG As Long: dwVendorInfo As Long
End Type
Public Type SockAddr: sin_family As Integer: sin_port As Integer: sin_addr As String * 4: sin_zero As String * 8: End Type
Public Type Inet_Address: Byte4 As String * 1: Byte3 As String * 1: Byte2 As String * 1: Byte1 As String * 1: End Type
Public Type T_Host: h_name As Long: h_aliases As Long: h_addrtype As Integer: h_length As Integer: h_addr_list As Long: End Type
 
Public Declare Function WSAGetLastError Lib "wsock32" () As Long
Public Declare Function WSAStartup Lib "wsock32" (ByVal wVersionRequired As Long, lpWSADATA As WSAData) As Long
Public Declare Function WSACleanUp Lib "wsock32" Alias "WSACleanup" () As Long
Public Declare Function GetHostName Lib "wsock32" Alias "gethostname" (ByVal szHost As String, ByVal dwHostLen As Long) As Long
Public Declare Function GetHostByName Lib "wsock32" Alias "gethostbyname" (ByVal szHost As String) As Long
Public Declare Function GetHostByAddr Lib "wsock32" Alias "gethostbyaddr" (addr As Long, ByVal addr_len As Long, ByVal addr_type As Long) As Long
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (xDest As Any, xSource As Any, ByVal nbytes As Long)
Public Declare Function inet_addr Lib "wsock32" (ByVal S As String) As Long
 
Public WSA_Data As WSAData, IPStruct As Inet_Address
 
' =====================================================================================================

Function HostByName(sHost As String) As String
 
    Dim S As String, p As Long, Host As T_Host, ListAddress As Long, ListAddr As Long, Address As Long
    S = String(64, 0): p = GetHostByName(sHost)
    If p = SOCKET_ERROR Then
        Exit Function
    Else
        If p <> 0 Then
            CopyMemory Host.h_name, ByVal p, Len(Host): ListAddress = Host.h_addr_list
            CopyMemory ListAddr, ByVal ListAddress, 4: CopyMemory Address, ByVal ListAddr, 4
            HostByName = InetAddrLongToString(Address)
        Else
            HostByName = "No DNS Entry"
        End If
    End If
End Function
 
Private Function InetAddrLongToString(Address As Long) As String
    CopyMemory IPStruct, Address, 4
    InetAddrLongToString = CStr(Asc(IPStruct.Byte4)) & "." & CStr(Asc(IPStruct.Byte3)) & _
                           "." & CStr(Asc(IPStruct.Byte2)) & "." & CStr(Asc(IPStruct.Byte1))
End Function
 
Function HostByAddress(ByVal sAddress As String) As String
    Dim lAddress As Long, p As Long, HostName As String, Host As T_Host
    lAddress = inet_addr(sAddress)
    p = GetHostByAddr(lAddress, 4, PF_INET)
    If p <> 0 Then
        CopyMemory Host, ByVal p, Len(Host): HostName = String(256, 0)
        CopyMemory ByVal HostName, ByVal Host.h_name, 256
        If HostName = "" Then HostByAddress = "Unable to Resolve Address"
        If InStr(HostName, Chr(0)) > 0 Then HostByAddress = Left(HostName, InStr(HostName, Chr(0)) - 1)
    Else
        HostByAddress = ""
    End If
End Function

Sub ПримерИспользования()
    'В начале работы вы должны использовать функцию WSAStartup
    WSAStartup &H101, WSA_Data
 
    'Определение имени машины, зная ее IP-адрес
    Debug.Print HostByAddress("87.250.250.11")  ' возвращает "yandex.ru"
    Debug.Print HostByAddress("209.85.143.99")  ' возвращает "dy-in-f99.1e100.net"

    'Определение IP адреса машины, зная ее доменное имя
    Debug.Print HostByName("yandex.ru")    ' возвращает 87.250.250.11
    Debug.Print HostByName("google.com")    ' возвращает 209.85.143.99

    'В конце работы вы должны использовать функцию WSACleanUp
    WSACleanUp
End Sub

Комментарии

Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Сохранить установки".

Function ResolveAddress(ByVal ComputerName$) As String
' выполняет ICMP запрос (ping) до адреса ComputerName
' возвращает IP-адрес ComputerName$
Dim oPingResult As Variant: On Error Resume Next
For Each oPingResult In GetObject("winmgmts://./root/cimv2").ExecQuery _
("SELECT * FROM Win32_PingStatus WHERE Address = '" & ComputerName & "'")
If IsObject(oPingResult) Then ResolveAddress = oPingResult.ProtocolAddress
Next
End Function

Подскажите пожалуйста как сделать так чтобы вышеуказанная функция выдавала IP адрес в формате ipv4 а не в ipv6?

Возможно, у вас 64-битная система, а код я писал для 32-битной, - надо дорабатывать код функций WinAPI

Добрый день. Пробовал использовать Ваш код в Vba для поиска IP смартфона (Android) по сетевому имени. В debug пишет "No DNS Entry". Сетевое имя нашел через функцию HostByAddress. С чем это (в смысле ошибка) может быть связано?

Отправить комментарий

Содержание этого поля является приватным и не предназначено к показу.
CAPTCHA
Подтвердите, пожалуйста, что вы - человек:
  ___           ____   _       _       _   _ 
|_ _| ___ / ___| | |__ | |__ | | | |
| | / __| | | | '_ \ | '_ \ | |_| |
| | | (__ | |___ | | | | | |_) | | _ |
|___| \___| \____| |_| |_| |_.__/ |_| |_|
Введите код, изображенный в стиле ASCII-арт.

Не получается применить макрос? Не удаётся изменить код под свои нужды?

Оформите заказ у нас на сайте, не забыв прикрепить примеры файлов, и описать, что и как должно работать.