11

What is the least cumbersome (module-inclusion, code lenght, etc) way to retrieve the machine IP address (of the first interface open)? I know of some solutions using MSINET, but I believe we can do better. Don't reply

Function HomeIP() as Atring
HomeIP= "127.0.0.1"
End Function

because it's not that funny... or correct. The scenario is a question wiht a document ID feature I'm trying to build a reply for.

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
jpinto3912
  • 1,457
  • 2
  • 12
  • 19
  • I thought that IP address may be part of the Environment variables and be obtained using Environ([index or name]), but unfortunately it isn't – Russ Cam May 07 '09 at 08:52
  • See: [Perform IP Lookups and resolve addresses](http://www.mvps.org/access/api/api0067.htm) – Mitch Wheat May 06 '09 at 07:56

7 Answers7

24

Here's an adapted example from Technet:

Function GetIPAddress()
    Const strComputer As String = "."   ' Computer name. Dot means local computer
    Dim objWMIService, IPConfigSet, IPConfig, IPAddress, i
    Dim strIPAddress As String

    ' Connect to the WMI service
    Set objWMIService = GetObject("winmgmts:" _
        & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

    ' Get all TCP/IP-enabled network adapters
    Set IPConfigSet = objWMIService.ExecQuery _
        ("Select * from Win32_NetworkAdapterConfiguration Where IPEnabled=TRUE")

    ' Get all IP addresses associated with these adapters
    For Each IPConfig In IPConfigSet
        IPAddress = IPConfig.IPAddress
        If Not IsNull(IPAddress) Then
            strIPAddress = strIPAddress & Join(IPAddress, ", ")
        End If
    Next

    GetIPAddress = strIPAddress
End Function

It requires that you have Microsoft WMI Scripting Library in the project's references.

Helen
  • 87,344
  • 17
  • 243
  • 314
  • Well Done! Very compact, although a truly "write-only" code snippet... I'll study the WMI lib for the next 2 months, just to get an idea of what is being done here. BTW, welcome to SO. – jpinto3912 Jun 04 '09 at 13:42
  • No deep magic here actually. :) I added comments to explain what's being done. – Helen Jun 04 '09 at 17:00
  • 1
    FYI, WMI stands for Windows Management Intstumentation; it's a Windows component that provides a way to perform lots of hardware, software and network management tasks. Here're some useful links: Sesame Script: WMI Query Language (this one is fun :) http://www.microsoft.com/technet/scriptcenter/resources/begin/ss1206.mspx WMI Scripting Primer: http://www.microsoft.com/technet/scriptcenter/guide/sas_wmi_overview.mspx WMI Reference @ MSDN: http://msdn.microsoft.com/en-us/library/aa394582.aspx – Helen Jun 04 '09 at 17:02
  • Small quirk in the code, to properly space delimit, use `strIPAddress = strIPAddress & " " & Join(IPAddress)` – Jishan Dec 27 '20 at 01:33
2

A couple of examples I found:-

http://www.everythingaccess.com/tutorials.asp?ID=Get-all-IP-Addresses-of-your-machine

http://puremis.net/excel/code/079.shtml

EDIT

Here is the code from the first link with slight modification

Option Explicit

' VBA MODULE: Get all IP Addresses of your machine
' (c) 2005 Wayne Phillips (http://www.everythingaccess.com)
' Written 18/05/2005
'
' REQUIREMENTS: Windows 98 or above, Access 97 and above
'
' Please read the full tutorial here:
' http://www.everythingaccess.com/tutorials.asp?ID=Get-all-IP-Addresses-of-your-machine
'
' Please leave the copyright notices in place.
' Thank you.
'
'Option Compare Database

'A couple of API functions we need in order to query the IP addresses in this machine
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Public Declare Function GetIpAddrTable Lib "Iphlpapi" (pIPAdrTable As Byte, pdwSize As Long, ByVal Sort As Long) As Long

'The structures returned by the API call GetIpAddrTable...
Type IPINFO
    dwAddr As Long         ' IP address
    dwIndex As Long         ' interface index
    dwMask As Long         ' subnet mask
    dwBCastAddr As Long     ' broadcast address
    dwReasmSize As Long    ' assembly size
    Reserved1 As Integer
    Reserved2 As Integer
End Type

Public Function ConvertIPAddressToString(longAddr As Long) As String

    Dim IPBytes(3) As Byte
    Dim lngCount As Long

    'Converts a long IP Address to a string formatted 255.255.255.255
    'Note: Could use inet_ntoa instead

    CopyMemory IPBytes(0), longAddr, 4 ' IP Address is stored in four bytes (255.255.255.255)

    'Convert the 4 byte values to a formatted string
    While lngCount < 4

        ConvertIPAddressToString = ConvertIPAddressToString + _
                                    CStr(IPBytes(lngCount)) + _
                                    IIf(lngCount < 3, ".", "")

        lngCount = lngCount + 1

    Wend

End Function

Public Function GetFirstNonLocalIPAddress()

    Dim Ret As Long, Tel As Long
    Dim bytBuffer() As Byte
    Dim IPTableRow As IPINFO
    Dim lngCount As Long
    Dim lngBufferRequired As Long
    Dim lngStructSize As Long
    Dim lngNumIPAddresses As Long
    Dim strIPAddress As String

On Error GoTo ErrorHandler:

    Call GetIpAddrTable(ByVal 0&, lngBufferRequired, 1)

    If lngBufferRequired > 0 Then

        ReDim bytBuffer(0 To lngBufferRequired - 1) As Byte

        If GetIpAddrTable(bytBuffer(0), lngBufferRequired, 1) = 0 Then

            'We've successfully obtained the IP Address details...

            'How big is each structure row?...
            lngStructSize = LenB(IPTableRow)

            'First 4 bytes is a long indicating the number of entries in the table
            CopyMemory lngNumIPAddresses, bytBuffer(0), 4

            While lngCount < lngNumIPAddresses

                'bytBuffer contains the IPINFO structures (after initial 4 byte long)
                CopyMemory IPTableRow, _
                            bytBuffer(4 + (lngCount * lngStructSize)), _
                            lngStructSize

                strIPAddress = ConvertIPAddressToString(IPTableRow.dwAddr)

                If Not ((strIPAddress = "127.0.0.1")) Then

                    GetFirstNonLocalIPAddress = strIPAddress
                    Exit Function

                End If

                lngCount = lngCount + 1

            Wend

        End If

    End If

Exit Function

ErrorHandler:
    MsgBox "An error has occured in GetIPAddresses():" & vbCrLf & vbCrLf & _
            Err.Description & " (" & CStr(Err.Number) & ")"

End Function
Adam Ralph
  • 29,453
  • 4
  • 60
  • 67
  • hmmm.. I'll try, skrink it till I can't understand the code anymore, and if it still works, you got it. – jpinto3912 May 06 '09 at 08:29
  • The first link code is good (the second can't be, need own pc name). It's compact, non-outside dependent, and I think the api won't change. I ask that you copy-paste that code here, keep the copyright notice, but let's mod the Sub to be a Function w/ no args (meaning lets always filter 127.0.0.1) returning the string. I'll mark it correct. Thanks, and well done! – jpinto3912 May 06 '09 at 20:59
  • thanks very much - I've made the edit you requested. sorry about the formatting - stackoverflow doesn't seem to be very VBA friendly ;-) – Adam Ralph May 07 '09 at 08:47
  • Whoah, that is a *lot* of code for doing something so trivial. – sybreon May 07 '09 at 11:55
  • well, it's not my code ;-) but does do the job apparently. Although perhaps it's not as trivial as you think? – Adam Ralph May 07 '09 at 12:18
  • GetIPAddresses shoul be renamed to GetSelfIPAddress, and must return String. Down to the bone of the function, please delete the comment (but before, read it!) and replace Debug.Print with GetSelfIPAddress=strIPAddress. Your public will appreciate... – jpinto3912 May 07 '09 at 21:39
  • Can someone at least edit the < Debug.Print strIPAddress > part (making it return the wanted strIPAddress string) so that the answer can be closed? thank you. – jpinto3912 Jun 03 '09 at 19:36
  • Sorry Adam, didn't mean to be fussy... this is vba, so the likelihood that someone just copy-pastes code from an SO reply, and if it doesn't work as planned, just gives up (no proper debug skills), is real. Helen just brought us a more compact answer although requiring WMI scripting...I've weighted the benefits/cons, and marked her proposal the right one (believing that reduced code size but having 1 extra reference inclusion isn't a big turn off for the regular vba guy). – jpinto3912 Jun 04 '09 at 13:51
1

You could execute the shell command ipconfig and parse the returned results?

sybreon
  • 3,128
  • 18
  • 19
  • We could redirect the cmd output to a txt... but try ipconfig on win2000, xp and vista and you'll see why that is a big messy no-no. – jpinto3912 May 06 '09 at 08:22
  • I'm not sure why is this messy? Could you elaborate? – sybreon May 06 '09 at 09:00
  • The required Token doesn't always appear on the same place, not surrounded by the same words. A final killer is that locale defs change the wording surrounding the IP-field token. To handle this, even through regex, would be far from trivial. – jpinto3912 May 06 '09 at 10:28
  • Not meaning to sound obtuse, but shouldn't it just be the first line with N.N.N.N in it (where N is an 8-bit number)? – sybreon May 06 '09 at 12:38
  • on XP that could be either DNS sufix, self IP address or gateway (depending on SPn) – jpinto3912 May 06 '09 at 20:52
1

There is another easy way using ipconfig. http://www.vbaexpress.com/kb/getarticle.php?kb_id=537

THEn
  • 1,920
  • 3
  • 28
  • 35
0
Option Explicit
Sub Main()

Dim wsh As Object
Dim strIPOutputFile As String, strSingleLine As String, strIP As String, strToFind As String
Dim intSourceFile As Integer, intLocation As Integer

    Set wsh = CreateObject("WScript.Shell")

    strIPOutputFile = "C:\Users\MeMeMeMe\Desktop\txtfile.txt"

'Save ipconfig info to file
    wsh.Run "%comspec% /c ipconfig/all> """ & strIPOutputFile & """

'Close any open text files
   Close

'Get the number of the next free text file
   intSourceFile = FreeFile

   Open strIPOutputFile For Input As intSourceFile

    strToFind = "IPv4 Address. . . . . . . . . . . :" 'This will probably depend on your file
   Do Until EOF(intSourceFile)
        Input #intSourceFile, strSingleLine
      If InStr(1, strSingleLine, strToFind) > 0 Then
        Exit Do
      End If
    Loop

    intLocation = Len(strToFind)
   strIP = Trim(Mid(strSingleLine,1 + intLocation,Len(strSingleLine) - intLocation))

    intLocation = Len(strIP)
    While Not IsNumeric(Mid(strIP,intLocation,1))
       strIP = Left(strIP, Len(strIP) - 1)
       intLocation = Len(strIP)
    Wend

    Close

   MsgBox strIP

End Sub
DonkeyKong
  • 1,005
  • 14
  • 18
0

Codeproject has a good article on how to do this with .net: http://www.codeproject.com/KB/cs/network.aspx

You could always create a console executable out of this, and call it from VBA.

RO

RichO
  • 723
  • 4
  • 7
0

nbtstat -n might do the job on XP anyway. Not sure about other Windows versions or about localisation in other languages. Partial sample output:

C:\Documents and Settings\colin>nbtstat -n

Local Area Connection: Node IpAddress: [192.168.1.100] Scope Id: []

            NetBIOS Local Name Table

etc.

barrowc
  • 10,444
  • 1
  • 40
  • 53
  • while it would be feasable to regex the result to tackle localization, it only works if netbios api is present... nowadays it's becoming ever more rare (due to security holes the size of jupiter) – jpinto3912 May 08 '09 at 15:05