调用 NetworkInterface.GetNetworkInterfaces() 获取所有网卡后,需筛选 OperationalStatus 为 Up、NetworkInterfaceType 非 Loopback/Tunnel/PointToPoint/Unknown 的接口,并排除 Description 含 VMware/VirtualBox/vEthernet/Docker 的虚拟网卡;再从其 UnicastAddresses 中提取 AddressFamily 为 InterNetwork 且非 169.254.x.x 的 IPv4 地址。

怎么用 NetworkInterface.GetNetworkInterfaces() 拿到所有网卡
直接调用 NetworkInterface.GetNetworkInterfaces() 会返回系统里全部网卡,包括 VMware、VirtualBox、Docker、Hyper-V 创建的虚拟适配器,甚至 Loopback(本地回环)也会混在里面。这不是你想要的“真实物理网卡 IP”,得筛。
关键判断点不是名字含不含 “Virtual”,而是看 NetworkInterfaceType 和 OperationalStatus:
-
NetworkInterfaceType排除Loopback、Tunnel、PointToPoint、Unknown -
OperationalStatus必须是Up(否则连通性没保障) - 再结合
GetIPProperties().UnicastAddresses提取 IPv4 地址
怎么过滤掉 VMware/VirtualBox 这类虚拟网卡
光靠 NetworkInterfaceType 不够——很多虚拟网卡类型也标成 Ethernet 或 Wireless80211。真正可靠的方式是查 NetworkInterface.Description 和 NetworkInterface.Id 的组合特征:
- Windows 下,VMware 网卡描述通常含
VMware、VMnet;VirtualBox 含VirtualBox;Hyper-V 含vEthernet或Hyper-V - Docker Desktop 常见 ID 是
{...}格式,但描述含Docker或Default Switch - 别依赖
Name字段(比如 “以太网” 这种中文名不稳定,还可能被用户重命名)
示例过滤逻辑:
var interfaces = NetworkInterface.GetNetworkInterfaces()
.Where(nic => nic.OperationalStatus == OperationalStatus.Up
&& nic.NetworkInterfaceType != NetworkInterfaceType.Loopback
&& !nic.Description.Contains("VMware", StringComparison.OrdinalIgnoreCase)
&& !nic.Description.Contains("VirtualBox", StringComparison.OrdinalIgnoreCase)
&& !nic.Description.Contains("vEthernet", StringComparison.OrdinalIgnoreCase)
&& !nic.Description.Contains("Docker", StringComparison.OrdinalIgnoreCase));
为什么 UnicastAddresses 里有的地址不能用
一个网卡可能有多个 UnicastAddress,比如 IPv4 + IPv6、DHCP 分配的 + APIPA(169.254.x.x)、甚至隧道接口附带的临时地址。你真正要的是「可用的 IPv4 公网/局域网地址」:
- 优先选
Address.AddressFamily == AddressFamily.InterNetwork(即 IPv4) - 排除
IsIPv6LinkLocal、IsIPv6Multicast、IsIPv6SiteLocal(这些是 IPv6 内部地址) - 排除 IPv4 的 APIPA 地址:
address.Address.ToString().StartsWith("169.254.") - 注意:有些设备(如双网卡笔记本)可能同时有有线和无线两个 Up 状态的网卡,得全留着,别硬写死只取第一个
获取 IP 时容易漏掉的边界情况
实际部署中,下面这些情况不处理就会出错或返回空:
- 网卡启用了 IPv6 但禁用了 IPv4 →
UnicastAddresses里只有 IPv6,AddressFamily.InterNetwork匹配不到 - 某些企业环境启用 DHCP 但尚未获取到地址 →
OperationalStatus == Up但UnicastAddresses为空 - 管理员手动禁用了 IPv4 协议栈 → 网卡状态是 Up,但 IP 层根本没加载
- Windows 10/11 的“快速启动”可能导致休眠后部分网卡状态未刷新,重启后才正常
所以最终取地址前必须加空检查:if (ipProps.UnicastAddresses.Any(x => x.Address.AddressFamily == AddressFamily.InterNetwork))
最麻烦的其实是多宿主(multi-homed)机器——它有多个有效 IPv4,而业务逻辑往往只想要“默认路由出口”的那个。这时候就得调用 NetworkInterface.GetIPProperties().GatewayAddresses 配合路由表分析,已经超出基础筛选范围了










