Link to home
Start Free TrialLog in
Avatar of fruitloopy
fruitloopy

asked on

VB.NET - Get all IP Addresses from a remote PC

I have no problem pinging a remote computer to get its IP address programatically but many of our laptops will have 2 IP addresses assigned; one for the Wired network adapter and another for the wireless adapter.

The wireless adapter connects on a successful authentication to the network. When the user logs off the wireless adapter is no longer connected but generally the laptop will be on a dock with a live wired adapter.

Our issue is, when we need to log the user off and use remote desktop to log on we can no longer connect as we were using the wireless IP instead of the wired.
I need to be able to obtain both the wired and wireless IP addresses of these laptops. Is that possible?

So in summary. I click a button to PING the remote laptop and a textbox displays the results like:

Ethernet: 192.168.0.234
Wireless: 192.168.0.212

Is that possible?

Here's my current code:
Dim pingSender As New Ping()
            Dim options As New PingOptions
            Dim data As String = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
            Dim buffer() As Byte = Encoding.ASCII.GetBytes(data)
            Dim timeout As Integer = 80
            Dim reply As PingReply = pingSender.Send(Hostname)
            If reply.Status = IPStatus.Success Then
                txtPingResult.Text = String.Format("Ping Successful" & vbCrLf & "{0}", reply.Address.ToString())
            Else
                txtPingResult.ForeColor = Color.Red
                txtPingResult.Text = String.Format("No response from host")
            End If

Open in new window

Avatar of ste5an
ste5an
Flag of Germany image

You may use WMI to query the active NICs on the remote machine. See WMI Tasks: Networking.

E.g.

On Error Resume Next 
arrComputers = Array(".","hoffmann-04")
For Each strComputer In arrComputers
    WScript.Echo
    WScript.Echo "===================================="
    WScript.Echo "Computer: "& strComputer
    WScript.Echo "===================================="

    Set objWMIService = GetObject("winmgmts:\\" & strComputer& "\root\CIMV2") 	
	Set colNics = objWMIService.ExecQuery("Select * From Win32_NetworkAdapter Where NetConnectionID = 'Local Area Connection'")
	Set colNics = objWMIService.ExecQuery("Select * From Win32_NetworkAdapter")
	 
	For Each objNic in colNics
		Set colNicConfigs = objWMIService.ExecQuery("ASSOCIATORS OF {Win32_NetworkAdapter.DeviceID='" &  objNic.DeviceID & "'} WHERE AssocClass=Win32_NetworkAdapterSetting")
		For Each objNicConfig In colNicConfigs
			For Each strIPAddress in objNicConfig.IPAddress				
				WScript.Echo "Adapter Name: " & objNic.Name & ", IP Address: " &  strIPAddress 
			Next
		Next
	Next	
Next

Open in new window

Avatar of fruitloopy
fruitloopy

ASKER

In a broad way of speaking this kind of works. I just can't get it to display just Local Area Connection and Wireless Connection
Why not? You need to inspect the different properties do get what you want..

On Error Resume Next 
arrComputers = Array(".","hoffmann-04")
For Each strComputer In arrComputers
    WScript.Echo
    WScript.Echo "===================================="
    WScript.Echo "Computer: "& strComputer
    WScript.Echo "===================================="

    Set objWMIService = GetObject("winmgmts:\\" & strComputer& "\root\CIMV2") 		
	Set colNics = objWMIService.ExecQuery("Select * From Win32_NetworkAdapter")
	 
	For Each objNic in colNics
		Set colNicConfigs = objWMIService.ExecQuery("ASSOCIATORS OF {Win32_NetworkAdapter.DeviceID='" &  objNic.DeviceID & "'} WHERE AssocClass=Win32_NetworkAdapterSetting")
		For Each objNicConfig In colNicConfigs
			For Each strIPAddress in objNicConfig.IPAddress				
			  If strIPAddress <> "" Then
				WScript.Echo "NetConnectionID: " & objNic.NetConnectionID & ", IP Address: " &  strIPAddress 
			  End If
			Next
		Next
	Next	
Next

Open in new window

This would be easier if it was written in VB.NET and not VB
How hard could it be?

Using WMI and WMI .NET Overview.
How hard it is depends on your level of coding experience and how much help is received.

My code at the moment will fetch all IP addresses where enabled but I can't figure out how to differentiate between which adapter has which IP address:
Try
            Dim PC As String = txtHostname.Text
            Dim scope As New ManagementScope(("\\" & PC & "\root\cimv2"))
            scope.Connect()
            Dim query As New ObjectQuery("Select * From Win32_NetworkAdapter Where NetConnectionID = 'Local Area Connection'")
            Dim query2 As New ObjectQuery("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")
            Dim objects As ManagementObjectCollection = New ManagementObjectSearcher(scope, query).Get
            Dim objects2 As ManagementObjectCollection = New ManagementObjectSearcher(scope, query2).Get
            Dim lvi As New ListViewItem
            Dim nX As Integer
            For Each mObject As ManagementObject In objects
                For Each objNic As ManagementObject In objects2
                    nX += 1
                    lvi = ListView1.Items.Add(mObject("NetConnectionID"))
                    lvi.SubItems.Add(objNic("IPAddress")(0))
                Next
            Next
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

Open in new window


At the momnent the listview1 shows:

Adapter                                      IP Address
Local Area Connection            172.17.155.137
Local Area Connection            172.17.197.19
E.g.

 
Imports System.Management

Module Module1

    Sub Main()

        Const MANAGEMENT_PATH As String = "\\{0}\root\cimv2"
        Const NETWORK_ADAPTER_QUERY As String = "SELECT * FROM Win32_NetworkAdapter"
        Const NETWORK_ADAPTER_CONFIGURATION_QUERY As String = "ASSOCIATORS OF {{Win32_NetworkAdapter.DeviceID='{0}'}} WHERE AssocClass=Win32_NetworkAdapterSetting"

        Dim PC As String = "HOFFMANN-04"
        Dim scope As New ManagementScope(String.Format(MANAGEMENT_PATH, PC))
        scope.Connect()

        Dim networkAdapters As ManagementObjectCollection = New ManagementObjectSearcher(scope, New ObjectQuery(NETWORK_ADAPTER_QUERY)).Get
        For Each networkAdapter In networkAdapters
            Dim networkAdapterConfiguration As ManagementObjectCollection = New ManagementObjectSearcher(scope, New ObjectQuery(String.Format(NETWORK_ADAPTER_CONFIGURATION_QUERY, networkAdapter("DeviceID")))).Get

            For Each mo As ManagementObject In networkAdapterConfiguration
                For Each prop As PropertyData In mo.Properties
                    If prop.Name = "IPAddress" And Not prop.Value Is Nothing Then
                        Console.WriteLine(String.Format("DeviceID:        {0}", networkAdapter("DeviceID")))
                        Console.WriteLine(String.Format("Name:            {0}", networkAdapter("Name")))
                        Console.WriteLine(String.Format("NetConnectionID: {0}", networkAdapter("NetConnectionID")))
                        For Each ip As String In prop.Value
                            Console.WriteLine("    IP:          {0}", ip)
                        Next
                    End If
                Next
            Next
        Next

        Console.WriteLine("Done.")
        Console.ReadLine()

    End Sub

End Module

Open in new window

Thanks for the code, it works as a console application:
DeviceID:        7
Name:            Intel(R) 82579LM Gigabit Network Connection
NetConnectionID: Local Area Connection
    IP:          172.17.155.137
    IP:          fe80::3cc7:2fad:5883:12a9
DeviceID:        11
Name:            Intel(R) Centrino(R) Ultimate-N 6300 AGN
NetConnectionID: Wireless Network Connection
    IP:          172.17.197.19
    IP:          fe80::4c0e:7a29:fa31:a232
Done.

Open in new window

But I'm having trouble adapting this to a Windows form. After I run this code:
Imports System.Management

Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Main()
    End Sub

    Sub Main()

        Const MANAGEMENT_PATH As String = "\\{0}\root\cimv2"
        Const NETWORK_ADAPTER_QUERY As String = "SELECT * FROM Win32_NetworkAdapter"
        Const NETWORK_ADAPTER_CONFIGURATION_QUERY As String = "ASSOCIATORS OF {{Win32_NetworkAdapter.DeviceID='{0}'}} WHERE AssocClass=Win32_NetworkAdapterSetting"

        Dim PC As String = txtHostname.Text
        Dim scope As New ManagementScope(String.Format(MANAGEMENT_PATH, PC))
        scope.Connect()

        Dim networkAdapters As ManagementObjectCollection = New ManagementObjectSearcher(scope, New ObjectQuery(NETWORK_ADAPTER_QUERY)).Get
        For Each networkAdapter In networkAdapters
            Dim networkAdapterConfiguration As ManagementObjectCollection = New ManagementObjectSearcher(scope, New ObjectQuery(String.Format(NETWORK_ADAPTER_CONFIGURATION_QUERY, networkAdapter("DeviceID")))).Get

            For Each mo As ManagementObject In networkAdapterConfiguration
                For Each prop As PropertyData In mo.Properties
                    If prop.Name = "IPAddress" And Not prop.Value Is Nothing Then
                        tb1.AppendText(String.Format("DeviceID:        {0}", networkAdapter("DeviceID" & vbCrLf)))
                        tb1.AppendText(String.Format("Name:            {0}", networkAdapter("Name" & vbCrLf)))
                        tb1.AppendText(String.Format("NetConnectionID: {0}", networkAdapter("NetConnectionID" & vbCrLf)))
                        For Each ip As String In prop.Value
                            tb1.AppendText(String.Format("    IP:          {0}", ip))
                        Next
                    End If
                Next
            Next
        Next

    End Sub

End Class

Open in new window

I get this error:
System.Management.ManagementException was unhandled
  HResult=-2146233087
  Message=Not found 
  Source=System.Management
  StackTrace:
       at System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus errorCode)
       at System.Management.PropertyData.RefreshPropertyInfo()
       at System.Management.PropertyDataCollection.get_Item(String propertyName)
       at System.Management.ManagementBaseObject.GetPropertyValue(String propertyName)
       at System.Management.ManagementBaseObject.get_Item(String propertyName)
       at IPAddress.Form1.Main() in H:\Visual Studio Projects\IPAddress\IPAddress\Form1.vb:line 26
       at IPAddress.Form1.Button1_Click(Object sender, EventArgs e) in H:\Visual Studio Projects\IPAddress\IPAddress\Form1.vb:line 6
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(ApplicationContext context)
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
       at IPAddress.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

Open in new window

I've never had much experience with console applications so I'm not sure if there's something I am missing?
ASKER CERTIFIED SOLUTION
Avatar of ste5an
ste5an
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Awesome!
I had to change the code a bit as Visual Studio moaned that the Public Class WMINetworkAdapter was at the top.
I also removed Hostname, DeviceID and Name from the results as I have other code that does this.

Here's the results:

Local Area Connection
172.17.155.137
fe80::3cc7:2fad:5883:12a9
Wireless Network Connection
172.17.197.19
fe80::4c0e:7a29:fa31:a232

I do have two questions, sorry.
Is there a way of speeding this up? I can see in line 31 that this may be unnecessary as I don't need this info but I'm unsure how to change it.
Also, I tried to use a For-Next statement to only show the IPv4 address but it didnt work. Is there a way of doing this?

New code:
Imports System.Management
Imports System.Text

Public Class Form1

    Private Sub btnWmi_Click(sender As Object, e As EventArgs) Handles btnWmi.Click

        Dim wmiNetworkAdapters As List(Of WmiNetworkAdapter)

        QueryWmiNetworkAdapters(txtHostname.Text, wmiNetworkAdapters)
        txtResult.Clear()
        For Each WmiNetworkAdapter In wmiNetworkAdapters
            txtResult.Text += WmiNetworkAdapter.ToString
        Next

    End Sub

    Private Sub QueryWmiNetworkAdapters(hostname As String, ByRef wmiNetworkAdapters As List(Of WmiNetworkAdapter))

        Const MANAGEMENT_PATH As String = "\\{0}\root\cimv2"
        Const NETWORK_ADAPTER_QUERY As String = "SELECT * FROM Win32_NetworkAdapter"
        Const NETWORK_ADAPTER_CONFIGURATION_QUERY As String = "ASSOCIATORS OF {{Win32_NetworkAdapter.DeviceID='{0}'}} WHERE AssocClass=Win32_NetworkAdapterSetting"

        wmiNetworkAdapters = New List(Of WmiNetworkAdapter)

        Dim scope As New ManagementScope(String.Format(MANAGEMENT_PATH, hostname))
        scope.Connect()

        Dim networkAdapters As ManagementObjectCollection = New ManagementObjectSearcher(scope, New ObjectQuery(NETWORK_ADAPTER_QUERY)).Get
        For Each networkAdapter In networkAdapters
            Dim networkAdapterConfiguration As ManagementObjectCollection = New ManagementObjectSearcher(scope, New ObjectQuery(String.Format(NETWORK_ADAPTER_CONFIGURATION_QUERY, networkAdapter("DeviceID")))).Get

            For Each mo As ManagementObject In networkAdapterConfiguration
                For Each prop As PropertyData In mo.Properties
                    If prop.Name = "IPAddress" And Not prop.Value Is Nothing Then
                        Dim wmiNetworkAdapter As WmiNetworkAdapter = New WmiNetworkAdapter(networkAdapter("NetConnectionID"))

                        For Each ip As String In prop.Value

                            wmiNetworkAdapter.IPs.Add(ip)

                        Next

                            wmiNetworkAdapters.Add(wmiNetworkAdapter)
                    End If
                Next
            Next
        Next
    End Sub

End Class
Public Class WmiNetworkAdapter

    Public NetConnectionID As String
    Public IPs As List(Of String) = New List(Of String)

    Public Sub New(netConnectionID As String)

        Me.NetConnectionID = netConnectionID

    End Sub

    Public Overrides Function ToString() As String

        Dim result As StringBuilder = New StringBuilder
        result.AppendLine(String.Format(Me.NetConnectionID))
        For Each ip As String In Me.IPs
            result.AppendLine(String.Format(ip))
        Next

        ToString = result.ToString

    End Function

End Class

Open in new window


Thanks very much for your help, I've been working on this for three days now!
1) Nope, not really.

WMI queries are pre se "slow" or feel like having a high latency.

When you can distinguish your adapters before you query the IP's, then you can an addition If around it. E.g.

    Private Sub QueryWmiNetworkAdapters(hostname As String, ByRef wmiNetworkAdapters As List(Of WmiNetworkAdapter))

        Const MANAGEMENT_PATH As String = "\\{0}\root\cimv2"
        Const NETWORK_ADAPTER_QUERY As String = "SELECT * FROM Win32_NetworkAdapter"
        Const NETWORK_ADAPTER_CONFIGURATION_QUERY As String = "ASSOCIATORS OF {{Win32_NetworkAdapter.DeviceID='{0}'}} WHERE AssocClass=Win32_NetworkAdapterSetting"

        wmiNetworkAdapters = New List(Of WmiNetworkAdapter)

        Dim scope As New ManagementScope(String.Format(MANAGEMENT_PATH, hostname))
        scope.Connect()

        Dim networkAdapters As ManagementObjectCollection = New ManagementObjectSearcher(scope, New ObjectQuery(NETWORK_ADAPTER_QUERY)).Get
        For Each networkAdapter In networkAdapters
		    If networkAdapter("NetConnectionID").Contains("Connection") Then
				Dim networkAdapterConfiguration As ManagementObjectCollection = New ManagementObjectSearcher(scope, New ObjectQuery(String.Format(NETWORK_ADAPTER_CONFIGURATION_QUERY, networkAdapter("DeviceID")))).Get

				For Each mo As ManagementObject In networkAdapterConfiguration
					For Each prop As PropertyData In mo.Properties
						If prop.Name = "IPAddress" And Not prop.Value Is Nothing Then
							Dim wmiNetworkAdapter As WmiNetworkAdapter = New WmiNetworkAdapter(networkAdapter("NetConnectionID"))

							For Each ip As String In prop.Value
								wmiNetworkAdapter.IPs.Add(ip)
							Next
							
							wmiNetworkAdapters.Add(wmiNetworkAdapter)
						End If
					Next
				Next
			End If
        Next
    End Sub

Open in new window


2) An IPv6 always contains at least one ":", so this should work:

 
For Each ip As String In prop.Value
	If Not ip.Contains(":") Then
		wmiNetworkAdapter.IPs.Add(ip)
	End If
Next

Open in new window

That's absolutely awesome!
Thanks very much for your help.