如何在C#中以编程方式获取Windows 10的DNS后缀搜索列表
在Windows 10中用C#获取DNS后缀搜索列表
我来给你几个靠谱的解决方法,之前你用IPInterfaceProperties.DnsSuffix没成功,大概率是没找对正确的适配器,或者用错了属性——其实.DnsSuffix只返回单个主后缀,而我们要的搜索列表是.DnsSuffixSearchList属性,不过得先过滤有效的适配器才行。下面是三种可行的方案:
方法一:用.NET自带的NetworkInformation类(最简洁)
这个方法不需要额外引用,直接用System.Net.NetworkInformation命名空间就能搞定,关键是要过滤掉禁用的、回环的适配器,只看正在运行的网络接口:
using System.Collections.Generic; using System.Net.NetworkInformation; public static List<string> GetDnsSearchSuffixes() { var dnsSuffixes = new List<string>(); // 遍历所有网络适配器 foreach (var networkInterface in NetworkInterface.GetAllNetworkInterfaces()) { // 只保留启用状态、非回环的适配器 if (networkInterface.OperationalStatus == OperationalStatus.Up && networkInterface.NetworkInterfaceType != NetworkInterfaceType.Loopback) { var ipProperties = networkInterface.GetIPProperties(); // 获取DNS后缀搜索列表 string[] searchList = ipProperties.DnsSuffixSearchList; if (searchList != null && searchList.Length > 0) { dnsSuffixes.AddRange(searchList); } } } // 去重后返回 return dnsSuffixes.Distinct().ToList(); }
调用这个方法就能得到包含fred.com、george.com的列表了,之前你可能没过滤适配器,导致拿到的是无效接口的空属性。
方法二:用WMI查询(兼容性好)
如果上面的方法在某些特殊环境下不好用,可以试试WMI,它能直接查询系统的网络配置信息:
注意:需要在项目中添加System.Management引用(右键项目→添加引用→找到System.Management)。
using System.Collections.Generic; using System.Management; using System.Linq; public static List<string> GetDnsSearchSuffixesViaWmi() { var dnsSuffixes = new List<string>(); // 查询启用IP的网络适配器配置 using (var searcher = new ManagementObjectSearcher( "SELECT DNSDomainSuffixSearchOrder FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = TRUE")) { foreach (ManagementObject obj in searcher.Get()) { string[] searchOrder = obj["DNSDomainSuffixSearchOrder"] as string[]; if (searchOrder != null) { dnsSuffixes.AddRange(searchOrder); } } } return dnsSuffixes.Distinct().ToList(); }
方法三:调用Windows原生IP Helper API(最底层)
如果需要更底层的控制,可以直接调用Windows的GetAdaptersAddresses函数,这个方法能拿到最详细的网络信息:
using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Linq; public static class DnsSuffixHelper { // 定义IP_ADAPTER_ADDRESSES结构体(只保留需要的字段) [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] private struct IP_ADAPTER_ADDRESSES { public IntPtr Next; public uint ComboIndex; [MarshalAs(UnmanagedType.LPWStr)] public string AdapterName; [MarshalAs(UnmanagedType.LPWStr)] public string DnsSuffix; public IntPtr FirstDnsSuffixSearchList; // 省略其他非必需字段,完整定义可参考微软官方文档 } // 导入GetAdaptersAddresses函数 [DllImport("iphlpapi.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern uint GetAdaptersAddresses( uint family, uint flags, IntPtr reserved, IntPtr adapterAddresses, ref uint size); public static List<string> GetDnsSearchSuffixesViaApi() { var dnsSuffixes = new List<string>(); uint bufferSize = 0; // 第一次调用获取所需内存大小 GetAdaptersAddresses(0, 0, IntPtr.Zero, IntPtr.Zero, ref bufferSize); IntPtr buffer = Marshal.AllocHGlobal((int)bufferSize); try { uint result = GetAdaptersAddresses(0, 0, IntPtr.Zero, buffer, ref bufferSize); if (result == 0) // 调用成功 { IntPtr currentAdapter = buffer; while (currentAdapter != IntPtr.Zero) { var adapter = Marshal.PtrToStructure<IP_ADAPTER_ADDRESSES>(currentAdapter); // 遍历DNS后缀搜索列表链表 IntPtr currentSuffix = adapter.FirstDnsSuffixSearchList; while (currentSuffix != IntPtr.Zero) { var suffixEntry = Marshal.PtrToStructure<IP_ADAPTER_ADDRESSES>(currentSuffix); if (!string.IsNullOrEmpty(suffixEntry.DnsSuffix)) { dnsSuffixes.Add(suffixEntry.DnsSuffix); } currentSuffix = suffixEntry.Next; } currentAdapter = adapter.Next; } } } finally { Marshal.FreeHGlobal(buffer); // 释放内存 } return dnsSuffixes.Distinct().ToList(); } }
这三种方法里,首推第一种,简单直接,不需要额外依赖。如果第一种不行,再试试WMI或者API的方式。
内容的提问来源于stack exchange,提问作者Justin Tamblyn
相关产品推荐
相关产品推荐

