最可靠方式是调用NetworkInterface.GetAllNetworkInterfaces()获取所有网卡MAC,需过滤Loopback/Tunnel/Unknown类型,保留Ethernet/Wireless80211且OperationalStatus.Up、MAC非全零的网卡,并手动格式化为带冒号分隔的十六进制字符串。

获取本机所有网卡的 MAC 地址(C#)
直接调用 NetworkInterface.GetAllNetworkInterfaces() 是最常用且可靠的方式。它能列出所有物理和虚拟网卡,包括已禁用但驱动加载的接口。
- 只返回
OperationalStatus.Up的网卡可能漏掉某些场景(比如 DHCP 获取 IP 前的网卡),如需完整列表,不要过滤状态 -
GetPhysicalAddress().ToString()返回的是不含分隔符的大写十六进制字符串(如"001122334455"),需要手动格式化才符合常见显示习惯 - 某些虚拟网卡(如 Hyper-V、Docker、WSL2 虚拟交换机)也会返回有效 MAC,注意甄别是否为真实物理网卡
过滤出“真实有线/无线网卡”的 MAC(避免虚拟设备干扰)
仅靠 NetworkInterfaceType 不够准确(比如部分蓝牙或隧道接口也标为 Ethernet),建议组合判断:
- 排除
NetworkInterfaceType.Loopback、NetworkInterfaceType.Tunnel、NetworkInterfaceType.Unknown - 优先保留
NetworkInterfaceType.Ethernet和NetworkInterfaceType.Wireless80211 - 检查
OperationalStatus == OperationalStatus.Up且GetPhysicalAddress().ToString() != "000000000000" - 可进一步通过
NetworkInterface.GetIsNetworkAvailable()辅助判断网络连通性,但它不反映单个网卡状态
获取默认网关所在网卡的 MAC(实际业务中最常需要)
很多场景(如设备绑定、日志标识)真正需要的是“当前用于上网的那块网卡”的 MAC,而不是所有网卡。这时应结合路由表定位:
- 用
IPGlobalProperties.GetIPGlobalProperties().GetUnicastAddresses()获取本机所有 IPv4 单播地址 - 遍历
NetworkInterface.GetAllNetworkInterfaces(),匹配每个接口的GetIPProperties().GatewayAddresses是否包含默认网卡(通常网关地址非0.0.0.0且对应接口状态为 Up) - 更稳妥的做法是调用
route print或使用GetBestInterfaceEx(P/Invoke)查默认路由出口,但跨平台性差;.NET 6+ 推荐用NetworkInterface.GetIsNetworkAvailable()+ 主动探测外网(如 ping 8.8.8.8)再反查源地址所属接口
权限与运行时限制(容易踩坑)
在 Linux/macOS 上用 .NET Core/.NET 5+ 运行时获取 MAC 地址一般无需 root;但在 Windows 上,某些低权限沙箱环境(如 UWP、受限的 ClickOnce)可能无法读取全部网卡信息。
- Windows:如果程序以低完整性级别运行(如 IE 模式、部分企业策略限制),
GetAllNetworkInterfaces()可能抛出UnauthorizedAccessException - Linux:依赖
/sys/class/net/*/address文件,容器内若挂载不全(如--cap-drop=NET_ADMIN)会导致读取失败或返回空 - macOS:从 macOS 10.15(Catalina)起,App Sandbox 默认禁止访问网络接口硬件地址,需在 entitlements 中启用
com.apple.security.network.client并申请隐私描述(NSNetworkUsageDescription)
var interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var nic in interfaces)
{
if (nic.OperationalStatus == OperationalStatus.Up &&
(nic.NetworkInterfaceType == NetworkInterfaceType.Ethernet ||
nic.NetworkInterfaceType == NetworkInterfaceType.Wireless80211))
{
var mac = nic.GetPhysicalAddress().ToString();
if (!string.IsNullOrEmpty(mac) && mac != "000000000000")
{
Console.WriteLine($"{nic.Name}: {string.Join(":", mac.Select((c, i) => i % 2 == 0 ? mac.Substring(i, 2) : "").Where(s => !string.IsNullOrEmpty(s))))}");
}
}
}
真实环境中,MAC 地址可能被虚拟化层随机化、被管理员手动修改、或因驱动未加载而不可读——不能当作唯一可靠的设备标识符。尤其在云主机、容器、远程桌面等场景下,它的稳定性远低于 CPU 序列号或 TPM 绑定 ID。










