C# - Finding my machine's local IP Address and not the VM's
Asked Answered
K

4

11

I have a VirtualBox VM installed on my machine and as such there is an ethernet adapter that appears for it. I'm enumerating through the list of my machine's IP address via the following:

       public string GetLocalIpAddress()
       {
            try
            {
                string strHostName = Dns.GetHostName();

                // Then using host name, get the IP address list..
                IPHostEntry ipEntry = Dns.GetHostEntry(strHostName);

                foreach (IPAddress ip in ipEntry.AddressList)
                {
                    if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                    {
                        return string.Format("({0})", ip.ToString());
                    }
                }
            }
            catch(Exception e)
            {
                Global.ApplicationLog.AddApplicationLog(EnumAppEventTypes.SYSTEM_ERROR, e.ToString());
            }

            return "";
        }

My problem is that the virtual machine's ethernet adapter also catches on the condition:

if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)

Is there a way of picking out my machine's local ip address and disregarding my virtual machine's?

Kinnard answered 11/11, 2011 at 4:29 Comment(0)
S
5

You can disregard the Ethernet adapter by its name. As the VM Ethernet adapter is represented by a valid NIC driver, it is fully equivalent to the physical NIC of your machine from the OS's point of view.

Starshaped answered 11/11, 2011 at 4:48 Comment(6)
Unfortunately the IPAddress class does not seem to keep the ethernet adapter's name so I can't eliminate the VM ethernet adapter with that method.Kinnard
Yep, you may need to change your approach by using NetworkInterface.GetAllNetworkInterfaces() method. It will return all the interfaces, and then you can enumerate through all available IP addresses for each interface.Starshaped
Hi pennanth, I can't seem to find any member variables that shows the IP address inside the NetworkInterface class. Also correct me if I'm wrong but by using the Name of the NetworkInterface class you could break it by renaming the ethernet adapter names? I'm looking for a more reliable solution than thatKinnard
Well, there is no guaranteed way of telling the virtual NIC from the physical one. They both are represented by the real drivers, and do not carry any badge saying "I'm virtual". So, the only way of segregating your NICs is asking a user to mark virtual NICs (then you can use NIC's GUIDs to tell one from another).Starshaped
That's not the ideal solution I was looking for but from what you're saying there is no definite way of implementing it. Will mark your answer as the accepted one. Thanks for the information.Kinnard
Or you can use the mac-address, the first 6 characters are the vendor ID. For VMWare it is "005056"Eonism
M
13

I'm refining Andrej Arh's answer, as the IP Address reported by GatewayAddresses can also be "0.0.0.0" instead of just null:

    public static string GetPhysicalIPAdress()
    {
        foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
        {
            var addr = ni.GetIPProperties().GatewayAddresses.FirstOrDefault();
            if (addr != null && !addr.Address.ToString().Equals("0.0.0.0"))
            {
                if (ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
                {
                    foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
                    {
                        if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
                        {
                            return ip.Address.ToString();
                        }
                    }
                }
            }
        }
        return String.Empty;
    }
Molybdate answered 28/8, 2014 at 16:7 Comment(1)
This doesn't work if there is no gateway but the address is still physical.Katlin
S
7

There is one option. VM IP don't have Default Gateway, so, exclude all IP's without Default Gateway.

foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
    var addr = ni.GetIPProperties().GatewayAddresses.FirstOrDefault();
    if (addr != null)
    {
        if (ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
        {
            Console.WriteLine(ni.Name);
            foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
            {
                if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                {
                    Console.WriteLine(ip.Address.ToString());
                }
            }
        }
    }
}
Selfsatisfied answered 5/10, 2013 at 13:17 Comment(0)
A
7

Use WMI and check ConnectorPresent property for physical device.

public static string GetPhysicalIPAdress()
{
    foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
    {
        if (ConnectorPresent(ni))
        {
            if (ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
            {
                foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
                {
                    if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                    {
                        return ip.Address.ToString();
                    }
                }
            }
        }
    }
    return string.Empty;
}

private static bool ConnectorPresent(NetworkInterface ni)
{
    ManagementScope scope = new ManagementScope(@"\\localhost\root\StandardCimv2");
    ObjectQuery query = new ObjectQuery(String.Format(
        @"SELECT * FROM MSFT_NetAdapter WHERE ConnectorPresent = True AND DeviceID = '{0}'", ni.Id));
    ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
    ManagementObjectCollection result = searcher.Get();
    return result.Count > 0;
}
Anglophobia answered 17/10, 2016 at 14:6 Comment(1)
This worked for me with one tweak: I also checked that ni.OperationalStatus == OperationalStatus.Up. Without that extra check it was returning interfaces that were actually down.Uralic
S
5

You can disregard the Ethernet adapter by its name. As the VM Ethernet adapter is represented by a valid NIC driver, it is fully equivalent to the physical NIC of your machine from the OS's point of view.

Starshaped answered 11/11, 2011 at 4:48 Comment(6)
Unfortunately the IPAddress class does not seem to keep the ethernet adapter's name so I can't eliminate the VM ethernet adapter with that method.Kinnard
Yep, you may need to change your approach by using NetworkInterface.GetAllNetworkInterfaces() method. It will return all the interfaces, and then you can enumerate through all available IP addresses for each interface.Starshaped
Hi pennanth, I can't seem to find any member variables that shows the IP address inside the NetworkInterface class. Also correct me if I'm wrong but by using the Name of the NetworkInterface class you could break it by renaming the ethernet adapter names? I'm looking for a more reliable solution than thatKinnard
Well, there is no guaranteed way of telling the virtual NIC from the physical one. They both are represented by the real drivers, and do not carry any badge saying "I'm virtual". So, the only way of segregating your NICs is asking a user to mark virtual NICs (then you can use NIC's GUIDs to tell one from another).Starshaped
That's not the ideal solution I was looking for but from what you're saying there is no definite way of implementing it. Will mark your answer as the accepted one. Thanks for the information.Kinnard
Or you can use the mac-address, the first 6 characters are the vendor ID. For VMWare it is "005056"Eonism

© 2022 - 2024 — McMap. All rights reserved.