【网络编程】【Windows】操作网卡类

概述:在 windows 环境下,使用 wmi 修改网卡 ip+dns

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
//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;
}

【网络编程】【Windows】操作网卡类
https://hodlyounger.github.io/A_OS/Windows/网络helper/【网络编程】操作网卡类/
作者
mingming
发布于
2023年10月27日
许可协议