C# - 查找我机器的本地 IP 地址而不是 VM 的

Posted

技术标签:

【中文标题】C# - 查找我机器的本地 IP 地址而不是 VM 的【英文标题】:C# - Finding my machine's local IP Address and not the VM's 【发布时间】:2021-08-20 05:49:39 【问题描述】:

我的机器上安装了 VirtualBox VM,因此出现了一个以太网适配器。我正在通过以下方式枚举我机器的 IP 地址列表:

       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 "";
        

我的问题是虚拟机的以太网适配器也捕捉到了这种情况:

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

有没有办法找出我机器的本地 IP 地址而忽略我的虚拟机?

【问题讨论】:

【参考方案1】:

您可以忽略以太网适配器的名称。由于 VM 以太网适配器由有效的 NIC 驱动程序表示,因此从操作系统的角度来看,它完全等同于您机器的物理 NIC。

【讨论】:

不幸的是,IPAddress 类似乎没有保留以太网适配器的名称,因此我无法使用该方法消除 VM 以太网适配器。 是的,您可能需要使用 NetworkInterface.GetAllNetworkInterfaces() 方法更改您的方法。它将返回所有接口,然后您可以枚举每个接口的所有可用 IP 地址。 您好 pennanth,我似乎在 NetworkInterface 类中找不到任何显示 IP 地址的成员变量。如果我错了,也请纠正我,但是通过使用 NetworkInterface 类的名称,您可以通过重命名以太网适配器名称来破坏它?我正在寻找比这更可靠的解决方案 嗯,没有保证可以将虚拟网卡与物理网卡区分开来。他们都由真正的司机代表,并且没有任何徽章说“我是虚拟的”。因此,隔离 NIC 的唯一方法是要求用户标记虚拟 NIC(然后您可以使用 NIC 的 GUID 区分彼此)。 这不是我一直在寻找的理想解决方案,但根据您的说法,没有明确的实施方法。会将您的答案标记为已接受。感谢您提供信息。【参考方案2】:

只有一种选择。虚拟机 IP 没有默认网关,所以排除所有没有默认网关的 IP。

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());
                
            
        
    

【讨论】:

【参考方案3】:

我正在完善 Andrej Arh 的答案,因为 GatewayAddresses 报告的 IP 地址也可以是“0.0.0.0”,而不仅仅是 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;
    

【讨论】:

如果没有网关但地址仍然是物理地址,这不起作用。【参考方案4】:

使用 WMI 并检查物理设备的 ConnectorPresent 属性。

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;

【讨论】:

这对我来说只需要一个调整:我还检查了 ni.OperationalStatus == OperationalStatus.Up。如果没有额外的检查,它会返回实际上已关闭的接口。

以上是关于C# - 查找我机器的本地 IP 地址而不是 VM 的的主要内容,如果未能解决你的问题,请参考以下文章

C# - 连接到 (RAS) *** 时如何获取 IP 地址

从 C# 中的 IP 获取本地网络上的机器 MAC 地址

无法从主机 ping 本地 VM [关闭]

如何获取在本地机器上运行的虚拟机的 IP 地址 [关闭]

是否可以使用本地IP地址而不是域名来安装gitlab?

获取机器公网IP