【问题标题】:C# - Finding my machine's local IP Address and not the VM'sC# - 查找我机器的本地 IP 地址而不是 VM 的
【发布时间】: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 地址而忽略我的虚拟机?

【问题讨论】:

    标签: c#


    【解决方案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。如果没有额外的检查,它会返回实际上已关闭的接口。
      猜你喜欢
      • 1970-01-01
      • 2020-03-12
      • 2018-05-16
      • 2020-08-04
      • 1970-01-01
      • 2011-07-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多