使用SetInterfaceDnsSettings/GetInterfaceDnsSettings修改Windows DNS的C++问题
C++调用SetInterfaceDnsSettings/GetInterfaceDnsSettings的正确示例
错误原因分析
GetInterfaceDnsSettings返回87(ERROR_INVALID_PARAMETER):通常是未正确初始化INTERFACE_DNS_SETTINGS结构体的Version字段,或者传入的网络接口索引无效。SetInterfaceDnsSettings返回0但未生效:大概率是未指定正确的Flags(如未标记要修改DNS服务器地址),或者程序未以管理员权限运行。
完整示例代码
以下代码包含获取有效网络接口索引、调用GetInterfaceDnsSettings读取当前DNS,以及调用SetInterfaceDnsSettings修改DNS的完整流程:
#include <windows.h> #include <iphlpapi.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #pragma comment(lib, "iphlpapi.lib") // 获取第一个启用的以太网/Wi-Fi接口索引 DWORD GetActiveNetworkInterfaceIndex() { DWORD dwSize = 0; GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_INTERFACES, NULL, NULL, &dwSize); PIP_ADAPTER_ADDRESSES pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(dwSize); if (!pAddresses) { return 0; } if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_INTERFACES, NULL, pAddresses, &dwSize) != NO_ERROR) { free(pAddresses); return 0; } DWORD index = 0; for (PIP_ADAPTER_ADDRESSES pCurr = pAddresses; pCurr != NULL; pCurr = pCurr->Next) { // 筛选启用的以太网或Wi-Fi接口 if (pCurr->OperStatus == IfOperStatusUp && (pCurr->IfType == IF_TYPE_ETHERNET_CSMACD || pCurr->IfType == IF_TYPE_IEEE80211)) { index = pCurr->IfIndex; break; } } free(pAddresses); return index; } int main() { DWORD dwInterfaceIndex = GetActiveNetworkInterfaceIndex(); if (dwInterfaceIndex == 0) { printf("未找到有效网络接口\n"); return 1; } printf("目标接口索引: %lu\n", dwInterfaceIndex); // 读取当前DNS配置 INTERFACE_DNS_SETTINGS dnsSettings = {0}; dnsSettings.Version = INTERFACE_DNS_SETTINGS_VERSION_1; // 必须指定正确版本 DWORD dwResult = GetInterfaceDnsSettings(dwInterfaceIndex, &dnsSettings); if (dwResult != NO_ERROR) { printf("GetInterfaceDnsSettings 失败,错误码: %lu\n", dwResult); return 1; } if (dnsSettings.NameServer[0]) { printf("当前DNS服务器: %s\n", dnsSettings.NameServer); } else { printf("当前未设置DNS服务器\n"); } // 修改DNS服务器地址 INTERFACE_DNS_SETTINGS newDnsSettings = {0}; newDnsSettings.Version = INTERFACE_DNS_SETTINGS_VERSION_1; newDnsSettings.Flags = DNS_SETTING_NAMESERVER; // 标记要修改DNS服务器项 // 设置主备DNS,用空格分隔,确保不超出数组长度 strncpy_s(newDnsSettings.NameServer, sizeof(newDnsSettings.NameServer), "8.8.8.8 8.8.4.4", _TRUNCATE); dwResult = SetInterfaceDnsSettings(dwInterfaceIndex, &newDnsSettings); if (dwResult != NO_ERROR) { printf("SetInterfaceDnsSettings 失败,错误码: %lu\n", dwResult); return 1; } printf("DNS服务器修改成功\n"); // 验证修改结果 ZeroMemory(&dnsSettings, sizeof(dnsSettings)); dnsSettings.Version = INTERFACE_DNS_SETTINGS_VERSION_1; dwResult = GetInterfaceDnsSettings(dwInterfaceIndex, &dnsSettings); if (dwResult == NO_ERROR && dnsSettings.NameServer[0]) { printf("修改后DNS服务器: %s\n", dnsSettings.NameServer); } return 0; }
关键注意事项
- 管理员权限:修改DNS需要程序以管理员身份运行,否则
SetInterfaceDnsSettings可能返回0但实际未生效。 - 结构体Version字段:必须设置为
INTERFACE_DNS_SETTINGS_VERSION_1(当前唯一可用版本),否则会触发参数错误。 - Flags字段:调用
SetInterfaceDnsSettings时,必须通过Flags明确指定要修改的配置项,比如DNS_SETTING_NAMESERVER对应DNS服务器地址,DNS_SETTING_SEARCHLIST对应DNS搜索列表。 - 接口索引有效性:确保传入的接口索引对应存在且启用的网络接口,可通过
GetAdaptersAddresses等API获取正确索引。
内容的提问来源于stack exchange,提问作者Gary Allen
相关产品推荐
相关产品推荐

