获取本机所有网卡的 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()可能抛出
UnauthorizedAccessExceptionLinux:依赖
/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。 