C语言中除GetNetworkParams外,有哪些函数可获取本机DNS服务器IP?
不用GetNetworkParams的Windows C语言取本地DNS方案
提GetNetworkParams大家都熟,就是IP Helper库里拿全局网络配置的常用函数,不想用它的话,有三个原生系统的实现路子,适配不同的依赖和兼容性要求:
用GetAdaptersAddresses枚举(最稳妥)
- 这个函数本身就是IP Helper系列的接口,XP SP2以上就自带,完全不依赖
GetNetworkParams - 实现逻辑很简单:先调一次拿需要的缓冲区大小,开够内存再调一次拿到全量的适配器配置链表
- 遍历返回的
IP_ADAPTER_ADDRESSES结构体就行,每个结构体里的FirstDnsServerAddress直接挂着这张网卡对应的DNS地址链表,顺着遍历就能把所有网卡的DNS都捞出来 - 好处是比
GetNetworkParams粒度细:GetNetworkParams只能返回全局的DNS,这个方法能按网卡拆分,搭配GetIpAddrTable找到默认路由走的那张出口网卡,就能拿到当前实际生效的DNS,不会混进那些断连的虚拟网卡的无效配置 - 实际踩过的坑:调用的时候千万别传
GAA_FLAG_SKIP_DNS_SERVER这个flag,传了的话直接就跳过DNS字段的返回,白折腾半天
直接读注册表(零额外库依赖)
- 其实Windows的DNS配置本来就存在注册表里,根本不需要关联IP Helper的库,编译的时候都能省掉iphlpapi.lib的依赖:
- 读IPv4 DNS的路径是
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\网卡GUID下面的NameServer(手动设置的静态DNS)和DhcpNameServer(DHCP自动分配的DNS) - 读IPv6 DNS就顺着找同结构路径下Tcpip6服务项对应的网卡GUID里的
NameServer值
- 读IPv4 DNS的路径是
- 注意点:得自己枚举所有网卡GUID对应的注册表项,把那些已经停用的网卡过滤掉;注册表写入比系统API返回慢几百毫秒,刚切换网络的时候读出来的配置可能有轻微偏差,常规场景下完全够用
WMI查询(适配企业域环境)
- 如果是公司域环境的设备,组策略下发的DNS有时候用前两个方法读出来会有滞后,这时候用COM初始化WMI连接,查
Win32_NetworkAdapterConfiguration类里IPEnabled = true的实例,读DNSServerSearchOrder属性,就能把包括组策略强制下发的DNS都拿到 - 这个方法的兼容性从Win2000开始就支持,就是代码量比前两个稍微多点,好处是不会漏域策略下发的配置
几个通用提醒
- 上面三个方法都是普通用户权限就能跑,不需要管理员权限,不会触发UAC弹窗
- 遇到拿不到DNS的情况,先检查是不是把处于断开状态的网卡给算进去了,这些网卡的DNS字段是空的
内容的提问来源于stack exchange,提问作者IGP
相关产品推荐
相关产品推荐

