c++ windows wmi修改网卡ip+dns

项目下载地址: https://github.com/w123l123h/netConfig

在win7/win10上都测试通过

注意事项:

  1. 项目必须以管理员权限运行
  2. 参考main.cpp使用方法
  3. 网卡的key可以从注册表获取, 路径: 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\
  4. 网卡key对应的中文名可以从注册表获取, 路径: 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Network{4D36E972-E325-11CE-BFC1-08002BE10318}\

注册表查看

网卡配置

注册表地址: 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces
in

网卡中文名

(和windows系统"控制面板\网络和 Internet\网络和共享中心"显示的名字一致)
注册表地址: 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Network{4D36E972-E325-11CE-BFC1-08002BE10318}
在这里插入图片描述

代码:

main.cpp

//main.cpp:

#include <iostream>
#include <locale>
#include <string>
#include <codecvt>
#include "net_config.h"

#pragma execution_character_set("utf-8")

using namespace std;

int main()
{
	std::locale::global(std::locale(""));

	NetConfig config;
	//网卡的key可以从注册表获取, 路径: 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\
	config.set_key("{cd574b17-73e1-42df-a50c-f95d7f15c1d0}");

	//设置静态ip之前要调用下enable_dhcp, 可以把以前设置的ip和网关都清空, 否则注册表会有多个ip信息
	if (config.enable_dhcp()) {
		cout << "enable_dhcp success" << endl;
	}
	else {
		cout << "error code: " << config.get_last_error_code() << endl;
	}
	
	if (config.set_ip_config("192.168.1.100", "255.255.255.0", "192.168.1.1")) {
		cout << "set_ip_config success" << endl;
	}
	else {
		cout << "error code: " << config.get_last_error_code() << endl;
	}

	if (config.set_dns("255.255.255.0", "")) {
		cout << "set_dns success" << endl;
	}
	else {
		cout << "error code: " << config.get_last_error_code() << endl;
	}				
	
	cin.get();
	return 0;
}

net_config.h

//net_config.h

#pragma once

#include <string>
#include <memory>
#include <vector>
#include <Wbemidl.h>

class NetConfig
{
public:
	NetConfig() {}
	NetConfig(const std::string &key) 
		:key_(key){ }
	~NetConfig();

	//设置网络设备GUID
	void set_key(const std::string &key) {
		clear();
		key_ = key;
	}
	//启用DHCP
	bool enable_dhcp();
	//启动静态IP,设置IP,掩码,网关
	bool set_ip_config(const std::string &ip, const std::string &mask, const std::string &gateway);
	bool set_ip_config(const std::string &ip, const std::string &mask);
	//设置网关
	bool set_gateway(const std::string &gateway);
	//设置DNS地址
	bool set_dns(const std::string &default_dns, const std::string &backup_dns);
	//设置自动DNS
	bool set_auto_dns();

	int get_last_error_code()const {
		return last_error_code_;
	}

	void clear();

private:
	NetConfig(const NetConfig &rhs) = delete;
	NetConfig &operator = (const NetConfig &rhs) = delete;

private:
	//初始化
	bool init();
	//创建COM数组
	std::shared_ptr<SAFEARRAY> create_SAFEARRAY(const std::vector<std::string> &args);
	bool set_dns_base(bool is_auto, const std::string &default_dns, const std::string &backup_dns);
	bool exec_method(const wchar_t *method, IWbemClassObject *params_instance);

private:
	std::string key_;
	bool is_init_ = false;
	IWbemLocator* p_instance_ = NULL;
	IWbemServices* p_service_ = NULL;
	IEnumWbemClassObject* p_enum_ = NULL;
	IWbemClassObject *p_obj_ = NULL;
	IWbemClassObject *p_config = NULL;
	VARIANT path_;
	int last_error_code_ = 0;
};

net_config.cpp

//net_config.cpp

#include "net_config.h"
#include <codecvt>
#include <atlbase.h>
#include <comutil.h>
#ifdef _DEBUG
#include <iostream>
#endif

#pragma comment(lib, "wbemuuid.lib")
#pragma comment(lib, "comsuppw.lib")

#pragma execution_character_set("utf-8")

using namespace std;

NetConfig::~NetConfig()
{
	clear();
}

bool NetConfig::enable_dhcp()
{
	if (!init())
		return false;
	return exec_method(L"EnableDHCP", NULL);
}

bool NetConfig::set_ip_config(const std::string & ip, const std::string & mask, const std::string & gateway)
{
	if (set_ip_config(ip, mask)) {
		return set_gateway(gateway);
	}
	return false;
}

bool NetConfig::set_ip_config(const std::string & ip, const std::string & mask)
{
	bool rt = false;
	if (!init())
		return rt;

	IWbemClassObject *params = NULL;
	IWbemClassObject *paramsInst = NULL;
	p_config->GetMethod(_bstr_t("EnableStatic"), 0, &params, NULL);
	params->SpawnInstance(0, &paramsInst);

	auto p1 = create_SAFEARRAY({ ip });
	VARIANT paramVt;
	paramVt.vt = VT_ARRAY | VT_BSTR;
	paramVt.parray = p1.get();
	paramsInst->Put(L"IPAddress", 0, &paramVt, NULL);
	p1 = create_SAFEARRAY({ mask });
	paramVt.parray = p1.get();
	paramsInst->Put(L"SubnetMask", 0, &paramVt, NULL);

	rt = exec_method(L"EnableStatic", paramsInst);
	if (params) {
		params->Release();
	}
	return rt;
}

bool NetConfig::set_dns(const std::string & default_dns, const std::string & backup_dns)
{
	return set_dns_base(false, default_dns, backup_dns);
}

bool NetConfig::set_auto_dns()
{
	return set_dns_base(true, "", "");
}

bool NetConfig::set_gateway(const std::string & gateway)
{
	bool rt = false;
	if (!init())
		return rt;

	IWbemClassObject *params = NULL;
	IWbemClassObject *paramsInst = NULL;
	p_config->GetMethod(_bstr_t("SetGateways"), 0, &params, NULL);
	params->SpawnInstance(0, &paramsInst);

	auto p1 = create_SAFEARRAY({ gateway });
	VARIANT paramVt;
	paramVt.vt = VT_ARRAY | VT_BSTR;
	paramVt.parray = p1.get();
	paramsInst->Put(L"DefaultIPGateway", 0, &paramVt, NULL);
	paramVt.vt = VT_UINT;
	paramVt.uintVal = 1;
	paramsInst->Put(L"GatewayCostMetric", 0, &paramVt, NULL);

	rt = exec_method(L"SetGateways", paramsInst);
	if (params) {
		params->Release();
	}
	return rt;
}

void NetConfig::clear()
{
	if (p_config) {
		p_config->Release();
		p_config = nullptr;
	}
	if (p_obj_) {
		p_obj_->Release();
		p_obj_ = nullptr;
	}
	if (p_enum_) {
		p_enum_->Release();
		p_enum_ = nullptr;
	}
	if (p_service_) {
		p_service_->Release();
		p_service_ = nullptr;
	}
	if (p_instance_) {
		p_instance_->Release();
		p_instance_ = nullptr;
	}
	if (is_init_) {
		CoUninitialize();
	}
	is_init_ = false;
}

bool NetConfig::init()
{
	if (is_init_) {
		return true;
	}

	// Step 1: Initialize COM.
	HRESULT	hres = CoInitializeEx(0, COINIT_MULTITHREADED);
	if (FAILED(hres)) {
#ifdef _DEBUG
		cout << "CoInitializeEx failed: " << hres << endl;
#endif
		return false;
	}

	/*
	// Step 2: Set general COM security levels
	hres = CoInitializeSecurity(
		NULL,
		-1,                          // COM negotiates service
		NULL,                        // Authentication services
		NULL,                        // Reserved
		RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 
		RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
		NULL,                        // Authentication info
		EOAC_NONE,                   // Additional capabilities 
		NULL                         // Reserved
	);
	//ASSERT_THROW(SUCCEEDED(hres), "CoInitializeSecurity failed");
	if (FAILED(hres)) {
#ifdef _DEBUG
		cout << "CoInitializeSecurity failed: " << hres << endl;
#endif
		return false;
	}
	*/

	// Step 3:  Obtain the initial locator to WMI
	hres = CoCreateInstance(
		CLSID_WbemLocator,
		0,
		CLSCTX_INPROC_SERVER,
		IID_IWbemLocator,
		(LPVOID*)&p_instance_);
	//ASSERT_THROW(SUCCEEDED(hres), "CoCreateInstance failed");
	if (FAILED(hres)) {
#ifdef _DEBUG
		cout << "CoCreateInstance failed: " << hres << endl;
#endif
		return false;
	}

	// Step 4: Connect to the local root\cimv2 namespace and obtain pointer pSvc to make IWbemServices calls.
	hres = p_instance_->ConnectServer(
		_bstr_t(L"ROOT\\CIMV2"),
		NULL,
		NULL,
		0,
		NULL,
		0,
		0,
		&p_service_
	);
	//ASSERT_THROW(SUCCEEDED(hres), "ConnectServer failed");
	if (FAILED(hres)) {
#ifdef _DEBUG
		cout << "ConnectServer failed: " << hres << endl;
#endif
		return false;
	}

	// Step 5:  Set security levels for the proxy
	hres = CoSetProxyBlanket(
		p_service_,                        // Indicates the proxy to set
		RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx 
		RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx 
		NULL,                        // Server principal name 
		RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 
		RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
		NULL,                        // client identity
		EOAC_NONE                    // proxy capabilities 
	);
	//ASSERT_THROW(SUCCEEDED(hres), "CoSetProxyBlanket failed");
	if (FAILED(hres)) {
#ifdef _DEBUG
		cout << "CoSetProxyBlanket failed: " << hres << endl;
#endif
		return false;
	}

	// 通过适配器名称来找到指定的适配器对象.
	CComBSTR TheQuery = L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE SettingID = \"";
	std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> conversion;
	TheQuery += conversion.from_bytes(key_).c_str();
	TheQuery += L"\"";
	hres = p_service_->ExecQuery(
		//SysAllocString(L"WQL"),
		L"WQL",
		TheQuery,
		WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
		NULL,
		&p_enum_);
	//ASSERT_THROW(SUCCEEDED(hres), "ExecQuery failed");
	if (FAILED(hres)) {
#ifdef _DEBUG
		cout << "ExecQuery failed: " << hres << endl;
#endif
		return false;
	}
	
	// Get the adapter object.
	ULONG num = 0;
	hres = p_enum_->Next(WBEM_INFINITE, 1, &p_obj_, &num);
	//ASSERT_THROW(SUCCEEDED(hres), "Next failed");
	if (FAILED(hres)) {
#ifdef _DEBUG
		cout << "Next failed: " << hres << endl;
#endif
		return false;
	}

	//ASSERT_THROW(0 < num, "Next failed");
	if (num < 1) {
#ifdef _DEBUG
		cout << "Next failed num < 1" << endl;
#endif
		return false;
	}

	VariantInit(&path_);
	hres = p_obj_->Get(L"__PATH", 0, &path_, NULL, NULL);
	//ASSERT_THROW(SUCCEEDED(hres), "Get path failed");
	if (FAILED(hres)) {
#ifdef _DEBUG
		cout << "Get failed: " << hres << endl;
#endif
		return false;
	}
	hres = p_service_->GetObject(_bstr_t(L"Win32_NetworkAdapterConfiguration"), 0, NULL, &p_config, NULL);
	//ASSERT_THROW(SUCCEEDED(hres), "GetObject Win32_NetworkAdapterConfiguration failed");
	if (FAILED(hres)) {
#ifdef _DEBUG
		cout << "GetObject failed: " << hres << endl;
#endif
		return false;
	}
	is_init_ = true;
	return true;
}

std::shared_ptr<SAFEARRAY> NetConfig::create_SAFEARRAY(const std::vector<std::string> &args)
{
	SAFEARRAY *psa = SafeArrayCreateVector(VT_BSTR, 0, args.size());
	long idx[] = { 0 };
	for (int i = 0; i < args.size(); i++) {
		std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> conversion;
		BSTR ip = SysAllocString(conversion.from_bytes(args[i]).c_str());
		idx[0] = i;
		if (FAILED(SafeArrayPutElement(psa, idx, ip))) {
			return (false);
		}
		SysFreeString(ip);
	}
	return shared_ptr<SAFEARRAY>(psa, [](SAFEARRAY *psa) {SafeArrayDestroy(psa); });
}

bool NetConfig::set_dns_base(bool is_auto, const std::string & default_dns, const std::string & backup_dns)
{
	bool rt = false;
	if (!init())
		return rt;

	IWbemClassObject *params = NULL;
	IWbemClassObject *paramsInst = NULL;
	p_config->GetMethod(_bstr_t("SetDNSServerSearchOrder"), 0, &params, NULL);
	params->SpawnInstance(0, &paramsInst);

	shared_ptr<SAFEARRAY> p1;
	if (is_auto) {
		paramsInst->Put(L"DNSServerSearchOrder", 0, NULL, NULL);
	}
	else {
		if (backup_dns.size()) {
			p1 = create_SAFEARRAY({ default_dns, backup_dns });
		}
		else {
			p1 = create_SAFEARRAY({ default_dns });
		}
		VARIANT paramVt;
		paramVt.vt = VT_ARRAY | VT_BSTR;
		paramVt.parray = p1.get();
		paramsInst->Put(L"DNSServerSearchOrder", 0, &paramVt, NULL);
	}

	rt = exec_method(L"SetDNSServerSearchOrder", paramsInst);
	if (params) {
		params->Release();
	}
	return rt;
}

bool NetConfig::exec_method(const wchar_t * method, IWbemClassObject * params_instance)
{
	bool rt = false;
	IWbemClassObject *results = NULL;
	auto res = p_service_->ExecMethod(path_.bstrVal, _bstr_t(method), 0, NULL, params_instance, &results, NULL);
	if (SUCCEEDED(res)) {
		VARIANT vtRet;
		VariantInit(&vtRet);
		if (!FAILED(results->Get(L"ReturnValue", 0, &vtRet, NULL, 0))) {
			if (vtRet.uintVal == 0 || vtRet.uintVal == 1) {
				rt = true;
			}
			else {
				last_error_code_ = vtRet.uintVal;
#ifdef _DEBUG
				wcout << method << " failed, result: " << last_error_code_ << endl;
#endif
			}
		}
#ifdef _DEBUG
		else {
			cout << "ExecMethod Get ReturnValue failed: " << res << endl;
		}
#endif
		VariantClear(&vtRet);
		results->Release();
	}
#ifdef _DEBUG
	else {
		cout << "ExecMethod failed: " << res << endl;
	}
#endif	
	if (params_instance) {
		params_instance->Release();
	}
	return rt;
}

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要使用 C++ 通过 WMI 查询网卡的所有信息,您可以使用以下步骤: 1. 引用 WMI 类库。您可以在 Visual Studio 的“项目”菜单中选择“添加引用”,然后选择“System.Management”来添加类库。 2. 初始化 COM 库。您可以在程序的开头调用 CoInitializeEx 函数来初始化 COM 库。 3. 使用 COM 对象获取 WMI 服务对象。您可以使用 CoCreateInstance 函数创建 IWbemLocator 接口实例,并使用该实例的 ConnectServer 方法连接到本地或远程计算机上的 WMI 服务。 4. 使用 WMI 查询语言 (WQL) 获取 Win32_NetworkAdapter 类的实例。您可以使用 IWbemServices 接口的 ExecQuery 方法并指定查询语句来获取 Win32_NetworkAdapter 类的实例。 5. 遍历每个网卡实例并获取其属性。您可以使用 IWbemClassObject 接口的 Get 方法获取每个实例的属性,并将其存储在 C++ 变量中。 以下是一个简单的示例代码,它演示了如何使用 C++ 获取本地计算机上所有网卡的名称和描述: ```cpp #include <iostream> #include <comdef.h> #include <Wbemidl.h> #pragma comment(lib, "wbemuuid.lib") int main() { // 初始化 COM 库 HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); if (FAILED(hr)) { std::cerr << "Failed to initialize COM library. Error code: " << hr << std::endl; return 1; } // 获取 WMI 服务对象 IWbemLocator* pLocator = nullptr; hr = CoCreateInstance(CLSID_WbemLocator, nullptr, CLSCTX_INPROC_SERVER, IID_IWbemLocator, reinterpret_cast<LPVOID*>(&pLocator)); if (FAILED(hr)) { std::cerr << "Failed to create IWbemLocator object. Error code: " << hr << std::endl; return 1; } IWbemServices* pServices = nullptr; hr = pLocator->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), nullptr, nullptr, 0, NULL, 0, 0, &pServices); if (FAILED(hr)) { std::cerr << "Failed to connect to WMI service. Error code: " << hr << std::endl; pLocator->Release(); return 1; } // 查询 Win32_NetworkAdapter 类的实例 IEnumWbemClassObject* pEnum = nullptr; hr = pServices->ExecQuery(_bstr_t(L"WQL"), _bstr_t(L"SELECT * FROM Win32_NetworkAdapter"), WBEM_FLAG_FORWARD_ONLY, nullptr, &pEnum); if (FAILED(hr)) { std::cerr << "Failed to execute WMI query. Error code: " << hr << std::endl; pServices->Release(); pLocator->Release(); return 1; } // 遍历网卡实例并获取属性 IWbemClassObject* pObject = nullptr; ULONG uReturned = 0; while (pEnum->Next(WBEM_INFINITE, 1, &pObject, &uReturned) == S_OK) { // 获取名称和描述 VARIANT varName, varDesc; hr = pObject->Get(L"Name", 0, &varName, nullptr, nullptr); if (FAILED(hr)) { std::cerr << "Failed to get Name property. Error code: " << hr << std::endl; pObject->Release(); continue; } hr = pObject->Get(L"Description", 0, &varDesc, nullptr, nullptr); if (FAILED(hr)) { std::cerr << "Failed to get Description property. Error code: " << hr << std::endl; VariantClear(&varName); pObject->Release(); continue; } // 输出名称和描述 std::wcout << L"Name: " << varName.bstrVal << std::endl; std::wcout << L"Description: " << varDesc.bstrVal << std::endl; // 释放对象和变量 VariantClear(&varName); VariantClear(&varDesc); pObject->Release(); } // 释放资源 pEnum->Release(); pServices->Release(); pLocator->Release(); CoUninitialize(); return 0; } ``` 请注意,这只是一个简单的示例,Win32_NetworkAdapter 类还有许多其他属性,您可以根据需要查询和获取它们。此外,WMI 查询是一种强大的技术,可以用于检索计算机上的各种系统信息。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值