Windows查看当前链路速率最稳定方式是WMI查询MSNetworkAdapterSetting类的LinkSpeed属性(单位bps),如1000000000=1Gbps;需先确认OperStatus为IfOperStatusUp,避免无效值。

Windows 上没有直接返回“当前链路速率”的单一 API,GetIfEntry2 和 GetIfTable2 返回的 dwSpeed 字段是适配器标称最大速率(如 1000000000 表示 1Gbps),不是实时协商速率;真实链路速率需查 NIC 驱动暴露的 OID 或 WMI。
用 WMI 查询 MSNetworkAdapterSetting 获取协商速率
这是最稳定、无需驱动权限、兼容 Win7+ 的方式。关键不是看 Speed(它和 GetIfEntry2 一样是标称值),而是查 LinkSpeed 属性 —— 它反映当前 PHY 协商结果:
-
LinkSpeed单位是 bps,例如1000000000表示 1Gbps,100000000是 100Mbps - 必须用
WQL查询SELECT LinkSpeed FROM MSNetworkAdapterSetting,不能用Win32_NetworkAdapter - 该类在部分精简系统或 Hyper-V 虚拟网卡上可能不存在,需加异常处理
- 查询延迟约 5–15ms,不建议高频轮询(
用 GetIfEntry2 + ifOperStatus 判断链路是否 UP
GetIfEntry2 本身不提供实时速率,但它能告诉你物理层是否连通,这是解读 LinkSpeed 的前提:
- 检查
pIfRow->OperStatus是否等于IfOperStatusUp;若为IfOperStatusDown,则LinkSpeed无意义 -
pIfRow->TransmitLinkSpeed和ReceiveLinkSpeed在 Windows 10 1809+ 才有效,且仍非实时 —— 它们只在链路重协商后更新,通常滞后数秒 - 务必用
ConvertInterfaceIndexToLuid获取 LUID,再传给GetIfEntry2;直接用接口索引调用会失败(错误码ERROR_INVALID_PARAMETER)
绕过 WMI:用 DeviceIoControl 发送 OID_GEN_LINK_SPEED
这是最底层、最准的方式,但风险高、兼容性差,仅推荐内网工具或已知硬件环境使用:
立即学习“C++免费学习笔记(深入)”;
- 需要打开网卡设备句柄:
CreateFile(L"\\.\{GUID}", ...),GUID 来自SetupDiEnumDeviceInterfaces - 调用
DeviceIoControl时,IOCTL_NDIS_QUERY_GLOBAL_STATS已废弃;必须用NDIS_OID_REQUEST结构体封装OID_GEN_LINK_SPEED - 返回值单位是 100bps(不是 bps),例如返回
10000000表示 1Gbps;需除以 10000 得 Mbps - 多数 Wi-Fi 驱动不支持该 OID;USB 网卡/雷电扩展坞常返回 0 或无效值;驱动签名强制开启时(Win10 RS5+)会直接拒绝未签名请求
真正可靠的方案是组合使用:先用 GetIfEntry2 拿 OperStatus 和 Luid,再用 WMI 查 MSNetworkAdapterSetting.LinkSpeed;遇到 WMI 不可用时降级为日志告警,而不是硬切到底层 IOCTL —— 后者容易因驱动差异导致 crash 或静默失败。


















