如何使用C++修改与设置Windows系统的DNS地址
Windows平台C++修改DNS实现方案
前置要求
- 编译时需链接
wbemuuid.lib和iphlpapi.lib库,上述代码已通过pragma指令自动配置链接 - 程序必须以管理员权限运行,否则WMI调用会因权限不足失败
- 仅支持Windows操作系统,实现逻辑与你提供的C#代码完全对齐
完整实现代码
#include <windows.h> #include <wbemcli.h> #include <iphlpapi.h> #include <iostream> #include <vector> #include <string> #pragma comment(lib, "wbemuuid.lib") #pragma comment(lib, "iphlpapi.lib") // 获取符合条件的活动以太网/WiFi网卡描述 std::wstring GetActiveNetworkInterfaceDesc() { ULONG bufLen = 0; GetAdaptersInfo(NULL, &bufLen); std::vector<BYTE> buf(bufLen); PIP_ADAPTER_INFO pAdapterInfo = reinterpret_cast<PIP_ADAPTER_INFO>(buf.data()); if (GetAdaptersInfo(pAdapterInfo, &bufLen) != ERROR_SUCCESS) { return L""; } while (pAdapterInfo) { // 筛选条件:状态连通、类型为以太网/WiFi、存在IPv4网关 if (pAdapterInfo->OperStatus == IfOperStatusUp && (pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET || pAdapterInfo->Type == IF_TYPE_IEEE80211)) { if (pAdapterInfo->GatewayList.IpAddress.String[0] != '\0') { // 网卡描述转为宽字符返回 int len = MultiByteToWideChar(CP_ACP, 0, pAdapterInfo->Description, -1, NULL, 0); std::wstring desc(len, 0); MultiByteToWideChar(CP_ACP, 0, pAdapterInfo->Description, -1, desc.data(), len); return desc; } } pAdapterInfo = pAdapterInfo->Next; } return L""; } // 设置指定网卡DNS bool SetDNS(const std::wstring& dnsAddr) { std::wstring targetDesc = GetActiveNetworkInterfaceDesc(); if (targetDesc.empty()) { std::wcout << L"未找到符合条件的活动网卡" << std::endl; return false; } HRESULT hres; hres = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { return false; } hres = CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL ); if (FAILED(hres)) { CoUninitialize(); return false; } IWbemLocator* pLoc = NULL; hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc); if (FAILED(hres)) { CoUninitialize(); return false; } IWbemServices* pSvc = NULL; hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc); if (FAILED(hres)) { pLoc->Release(); CoUninitialize(); return false; } hres = CoSetProxyBlanket( pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE ); if (FAILED(hres)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return false; } IEnumWbemClassObject* pEnumerator = NULL; hres = pSvc->ExecQuery( _bstr_t(L"WQL"), _bstr_t(L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = TRUE"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator ); if (FAILED(hres)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return false; } IWbemClassObject* pclsObj = NULL; ULONG uReturn = 0; bool success = false; while (pEnumerator) { HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if (uReturn == 0) break; VARIANT vtDesc; VariantInit(&vtDesc); hr = pclsObj->Get(L"Description", 0, &vtDesc, 0, 0); if (SUCCEEDED(hr) && wcscmp(vtDesc.bstrVal, targetDesc.c_str()) == 0) { IWbemClassObject* pClass = NULL; hr = pSvc->GetObject(_bstr_t(L"Win32_NetworkAdapterConfiguration"), 0, NULL, &pClass, NULL); if (SUCCEEDED(hr)) { IWbemClassObject* pInParamsDefinition = NULL; hr = pClass->GetMethod(L"SetDNSServerSearchOrder", 0, &pInParamsDefinition, NULL); if (SUCCEEDED(hr)) { IWbemClassObject* pInstance = NULL; hr = pInParamsDefinition->SpawnInstance(0, &pInstance); if (SUCCEEDED(hr)) { // 构造DNS地址数组 SAFEARRAY* psaDns = SafeArrayCreateVector(VT_BSTR, 0, 1); LONG index = 0; BSTR bstrDns = SysAllocString(dnsAddr.c_str()); SafeArrayPutElement(psaDns, &index, bstrDns); VARIANT vtDns; VariantInit(&vtDns); vtDns.vt = VT_ARRAY | VT_BSTR; vtDns.parray = psaDns; hr = pInstance->Put(L"DNSServerSearchOrder", 0, &vtDns, 0); if (SUCCEEDED(hr)) { VARIANT vtPath; VariantInit(&vtPath); hr = pclsObj->Get(L"__PATH", 0, &vtPath, 0, 0); if (SUCCEEDED(hr)) { IWbemClassObject* pOutParams = NULL; hr = pSvc->ExecMethod(vtPath.bstrVal, _bstr_t(L"SetDNSServerSearchOrder"), 0, NULL, pInstance, &pOutParams, NULL); if (SUCCEEDED(hr)) { VARIANT vtRet; VariantInit(&vtRet); hr = pOutParams->Get(L"ReturnValue", 0, &vtRet, NULL, 0); if (SUCCEEDED(hr) && vtRet.lVal == 0) { success = true; } VariantClear(&vtRet); pOutParams->Release(); } VariantClear(&vtPath); } } VariantClear(&vtDns); SafeArrayDestroy(psaDns); SysFreeString(bstrDns); pInstance->Release(); } pInParamsDefinition->Release(); } pClass->Release(); } } VariantClear(&vtDesc); pclsObj->Release(); } pEnumerator->Release(); pSvc->Release(); pLoc->Release(); CoUninitialize(); return success; } // 调用示例 int main() { // 示例设置为阿里公共DNS,可替换为需要的DNS地址 if (SetDNS(L"223.5.5.5")) { std::wcout << L"DNS设置成功" << std::endl; } else { std::wcout << L"DNS设置失败,请确认以管理员权限运行程序" << std::endl; } system("pause"); return 0; }
扩展说明
如果需要配置多个DNS地址,仅需调整SafeArrayCreateVector的长度参数,按顺序将多个DNS地址填入数组即可。
内容的提问来源于stack exchange,提问作者hugzho
相关产品推荐
相关产品推荐

