【网络编程】【Windows】监控指定网卡事件

[toc]

win com类和接口说明

1. INetworkListManager

INetworkListManager 接口提供了一组用于执行网络列表管理功能的方法。

[通过com组件获取系统网卡] INetworkListManager接口

INetworkListManager::ClearSimulatedProfileInfo 清除以前通过 SetSimulatedProfileInfo 应用于 Internet 连接配置文件的连接配置文件值。 下一个 Internet 连接查询(通过 GetInternetConnectionProfile)将使用系统信息。
INetworkListManager::get_IsConnected get_IsConnected 属性指定本地计算机是否具有网络连接。
INetworkListManager::get_IsConnectedToInternet get_IsConnectedToInternet 属性指定本地计算机是否具有 Internet 连接。
INetworkListManager::GetConnectivity GetConnectivity 方法返回计算机的整体连接状态。
INetworkListManager::GetNetwork GetNetwork 方法基于提供的网络 ID 检索网络。
INetworkListManager::GetNetworkConnection GetNetworkConnection 方法基于提供的网络连接 ID 检索网络。
INetworkListManager::GetNetworkConnections GetNetworkConnections 方法枚举已建立的网络连接的完整列表。
INetworkListManager::GetNetworks GetNetworks 方法检索本地计算机上可用的网络列表。
INetworkListManager::SetSimulatedProfileInfo SetSimulatedProfileInfo 方法将一组特定的连接配置文件值应用于 Internet 连接配置文件,以支持特定按流量计费的 Internet 连接条件模拟。

使用参考:

1
2
3
4
5
6
7
8
9
10
11
12
...
IUnknown* pUnknown = NULL;
HRESULT Result = CoCreateInstance(CLSID_NetworkListManager, NULL, CLSCTX_ALL, IID_IUnknown, (void**)&pUnknown);
if (SUCCEEDED(Result))
{
INetworkListManager* pNetworkListManager = NULL;
Result = pUnknown->QueryInterface(IID_INetworkListManager, (void**)&pNetworkListManager);
if (SUCCEEDED(Result))
{

}
...

2. INetConnectionManager

3. IConnectionPointContainer

支持可连接对象的连接点。

IConnectionPointContainer::EnumConnectionPoints 创建枚举器对象以循环访问可连接对象中支持的所有连接点,每个传出 IID 一个连接点。
IConnectionPointContainer::FindConnectionPoint 如果 IID 描述支持的传出接口,则返回指向指定 IID 的连接点的 IConnectionPoint 接口的指针。

使用参考:

1
2
3
4
5
6
7
8
9
10
11
12
13
...
IConnectionPointContainer* pCPContainer = NULL;
Result = pNetworkListManager->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPContainer);
if (SUCCEEDED(Result))
{
IConnectionPoint* pConnectPoint = NULL;
Result = pCPContainer->FindConnectionPoint(IID_INetworkListManagerEvents, &pConnectPoint); // 查找 IID 对应的连接点
if (SUCCEEDED(Result))
{

}
}
...

4. IConnectionPoint

支持可连接对象的连接点。通过 IConnectionPointContainer::FindConnectionPoint 获取。通过其函数 Advise 可以建立连接点对象与客户端接收器之间的连接。也就是可以通过此接口实现网络事件的监控。

使用参考:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
IConnectionPoint* pConnectPoint = NULL;
Result = pCPContainer->FindConnectionPoint(IID_INetworkListManagerEvents, &pConnectPoint);
if (SUCCEEDED(Result))
{
DWORD Cookie = NULL;

CNetworkMonitor networkMonitor;
std::function<void(bool)> monitorFunc = std::bind(&CNetworkMonitor::NetworkStatusChangedCallback, networkMonitor, std::placeholders::_1);
// CNetworkListManagerEvent 为继承自 INetworkListManagerEvents 的类,重载了 ConnectivityChanged 函数
CNetworkListManagerEvent* pNetEvent = new(std::nothrow) CNetworkListManagerEvent(monitorFunc);
if (pNetEvent)
{
Result = pConnectPoint->Advise((IUnknown*)pNetEvent, &Cookie);
...

5. INetConnection

https://learn.microsoft.com/en-us/windows/win32/api/netcon/nn-netcon-inetconnection

使用示例 1:

监控网络状态,同时可以监控wife的网络质量

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
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
#include <string>
#include <iostream>
#include <memory>
#include <thread>
#include <vector>
#include <algorithm>
#include <locale>
#include <codecvt>
#include <functional>

#include <Windows.h>
#include <netlistmgr.h>
#include <atlbase.h>
#include <objbase.h>
#include <wtypes.h>
#include <wlanapi.h>
#include <netcon.h>
#include <IPHlpApi.h>
#include <comutil.h>
#pragma comment(lib, "comsuppwd.lib")


#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "wlanapi.lib")
#pragma comment(lib, "Iphlpapi.lib")

static std::string WCharToMByte(LPCWSTR lpcwszStr)
{
std::string str;
DWORD dwMinSize = 0;
LPSTR lpszStr = NULL;
dwMinSize = WideCharToMultiByte(CP_OEMCP, NULL, lpcwszStr, -1, NULL, 0, NULL, FALSE);
if (0 == dwMinSize)
{
return FALSE;
}
lpszStr = new char[dwMinSize];
WideCharToMultiByte(CP_OEMCP, NULL, lpcwszStr, -1, lpszStr, dwMinSize, NULL, FALSE);
str = lpszStr;
delete[] lpszStr;
return str;
}

static std::wstring GUIDToString(const GUID& guid)
{
OLECHAR guidString[40] = { 0 };
::StringFromGUID2(guid, guidString, sizeof(guidString));
return guidString;
}

static std::string UnicodeToUTF8(const std::wstring& wstr)
{
std::string ret;
try
{
std::wstring_convert< std::codecvt_utf8<wchar_t> > wcv;
ret = wcv.to_bytes(wstr);
}
catch (const std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return ret;
}

class NetWorkEvent : public INetworkConnectionEvents
{
private:
LONG _ref;
std::function<void()> _callback;

public:
NetWorkEvent(const std::function<void()>& cb);

virtual HRESULT STDMETHODCALLTYPE NetworkConnectionConnectivityChanged(
/* [in] */ GUID connectionId,
/* [in] */ NLM_CONNECTIVITY newConnectivity);

virtual HRESULT STDMETHODCALLTYPE NetworkConnectionPropertyChanged(
/* [in] */ GUID connectionId,
/* [in] */ NLM_CONNECTION_PROPERTY_CHANGE flags);

STDMETHODIMP QueryInterface(REFIID refIID, void** pIFace);
virtual ULONG __stdcall AddRef(void);
virtual ULONG __stdcall Release(void);
};

NetWorkEvent::NetWorkEvent(const std::function<void()>& cb)
: _callback(cb)
{
}

HRESULT NetWorkEvent::NetworkConnectionConnectivityChanged(GUID connectionId, NLM_CONNECTIVITY newConnectivity)
{
std::wcout << GUIDToString(connectionId) << " | NUL_CONNECTIVITY : " << newConnectivity << std::endl;
if (_callback)
{
_callback();
}
return S_OK;
}

HRESULT NetWorkEvent::NetworkConnectionPropertyChanged(GUID connectionId, NLM_CONNECTION_PROPERTY_CHANGE flags)
{
return S_OK;
}

STDMETHODIMP NetWorkEvent::QueryInterface(REFIID refIID, void** pIFace)
{
HRESULT hr = S_OK;
*pIFace = NULL;
if (IsEqualIID(refIID, IID_IUnknown))
{
*pIFace = (IUnknown*)this;
((IUnknown*)*pIFace)->AddRef();
}
else if (IsEqualIID(refIID, IID_INetworkConnectionEvents))
{
*pIFace = (INetworkConnectionEvents*)this;
((IUnknown*)*pIFace)->AddRef();
}
else
{
hr = E_NOINTERFACE;
}

return hr;
}

ULONG NetWorkEvent::AddRef(void)
{
return (ULONG)InterlockedIncrement(&_ref);
}

ULONG NetWorkEvent::Release(void)
{
LONG Result = InterlockedDecrement(&_ref);
if (Result == 0)
delete this;
return (ULONG)Result;
}

enum NetworkType
{
NotNetwork,
Ethernet,
Wlan,
};

enum WiFiQuality
{
Weak, // (-INF, -70dBm)
Fair, // [-70dBm, -60dBm)
Good, // [-60dBm, -50dBm)
Excellent // [-50dBm, +INF)
};

struct ConnectionInfo
{
std::wstring guid;
NetworkType type;
};

class NetworkMonitor
{
friend void OnNotificationCallback(PWLAN_NOTIFICATION_DATA Data, PVOID context);
public:
NetworkMonitor();
~NetworkMonitor();

std::vector<ConnectionInfo> GetNetworkConnections();
NetworkType GetNetAdpaterType(const std::wstring& guid);
void OnNetworkStatusChange();
WiFiQuality GetWiFiSignalQuality(const std::wstring& guid);
void OnWiFiQualityChange(const GUID& guid);

void ShowNetworkStatus();

private:
std::unique_ptr<NetWorkEvent> _networkEvent;

DWORD _cookie;
CComPtr<INetworkListManager> _pNLM;
CComPtr<IConnectionPointContainer> _pCpc;
CComPtr<IConnectionPoint> _pConnectionPoint;

HANDLE _wlanHandle;
};

static NetworkMonitor* InstanceOfNetworkMonitor()
{
static NetworkMonitor instance;
return &instance;
}

NetworkMonitor::NetworkMonitor()
{
CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);

HRESULT hr = CoCreateInstance(CLSID_NetworkListManager, NULL, CLSCTX_ALL, IID_INetworkListManager, (LPVOID*)&_pNLM);
hr = _pNLM->QueryInterface(IID_IConnectionPointContainer, (void**)&_pCpc);
hr = _pCpc->FindConnectionPoint(IID_INetworkConnectionEvents, &_pConnectionPoint);

_networkEvent = std::make_unique<NetWorkEvent>(std::bind(&NetworkMonitor::OnNetworkStatusChange, this));
hr = _pConnectionPoint->Advise((IUnknown*)_networkEvent.get(), &_cookie);
}

NetworkMonitor::~NetworkMonitor()
{
if (_pConnectionPoint)
{
_pConnectionPoint->Unadvise(_cookie);
}

CloseHandle(_wlanHandle);

CoUninitialize();
}

void OnNotificationCallback(PWLAN_NOTIFICATION_DATA Data, PVOID context)
{
if (Data != NULL &&
Data->NotificationSource == WLAN_NOTIFICATION_SOURCE_MSM &&
Data->NotificationCode == wlan_notification_msm_signal_quality_change)
{
WLAN_SIGNAL_QUALITY Qality = (WLAN_SIGNAL_QUALITY)Data->pData;
std::cout << "WiFi OnNotification Qality : " << Qality << std::endl;
InstanceOfNetworkMonitor()->OnWiFiQualityChange(Data->InterfaceGuid);
}
}

std::vector<ConnectionInfo> NetworkMonitor::GetNetworkConnections()
{
std::vector<ConnectionInfo> result;

CComPtr<IEnumNetworkConnections> enumConnectons;

if (FAILED(_pNLM->GetNetworkConnections(&enumConnectons)))
{
std::cerr << "GetNetworkConnections error : " << GetLastError() << std::endl;
return result;
}

if (enumConnectons)
{
ULONG lFetch;
INetworkConnection* connection = nullptr;
while (SUCCEEDED(enumConnectons->Next(1, &connection, &lFetch)) && nullptr != connection)
{

// 判断是否当前连接网卡
/*
VARIANT_BOOL isConnectInternet = VARIANT_FALSE;
connection->get_IsConnectedToInternet(&isConnectInternet);
if (isConnectInternet == VARIANT_FALSE)
{
continue;
}
*/

ConnectionInfo item;
GUID guid;
INetwork* network;
BSTR strNetWorkName = nullptr;

if (SUCCEEDED(connection->GetNetwork(&network)) && network != nullptr)
{
network->GetName(&strNetWorkName);
}

std::string strName = _com_util::ConvertBSTRToString(strNetWorkName);

if (strName.compare("TrustAgent VNIC") != 0)
{
continue;
}

// 获取 GUID
connection->GetAdapterId(&guid);
item.guid = GUIDToString(guid);

result.push_back(item);
}
if (connection)
{
connection->Release();
}
}

for (auto it = result.begin(); it != result.end(); ++it)
{
it->type = GetNetAdpaterType(it->guid);
}
std::partition(result.begin(), std::partition(result.begin(), result.end(), [](const ConnectionInfo& info)
{
return info.type != NetworkType::NotNetwork;
}), [](const ConnectionInfo& info)
{
return info.type == NetworkType::Ethernet;
});
for (auto it = result.begin(); it != result.end(); ++it)
{
std::wcout << "connect network guid : " << it->guid << " | type : " << it->type << std::endl;
}
return result;
}

NetworkType NetworkMonitor::GetNetAdpaterType(const std::wstring& guid)
{
unsigned long unSize = sizeof(IP_ADAPTER_INFO);
std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(unSize);
bool find = false;
unsigned long unResult = GetAdaptersInfo(reinterpret_cast<PIP_ADAPTER_INFO>(data.get()), &unSize);

if (ERROR_BUFFER_OVERFLOW == unResult)
{
data = std::make_unique<uint8_t[]>(unSize);
unResult = GetAdaptersInfo(reinterpret_cast<PIP_ADAPTER_INFO>(data.get()), &unSize);
}
if (ERROR_SUCCESS == unResult)
{
PIP_ADAPTER_INFO pIpAdapterInfo = reinterpret_cast<PIP_ADAPTER_INFO>(data.get());

while (pIpAdapterInfo)
{
if (UnicodeToUTF8(guid) == pIpAdapterInfo->AdapterName)
{
return MIB_IF_TYPE_ETHERNET == pIpAdapterInfo->Type ? NetworkType::Ethernet :
IF_TYPE_IEEE80211 == pIpAdapterInfo->Type ? NetworkType::Wlan : NetworkType::NotNetwork;
}
pIpAdapterInfo = pIpAdapterInfo->Next;
}
}

return NetworkType::NotNetwork;
}

void NetworkMonitor::OnNetworkStatusChange()
{
ShowNetworkStatus();
}

WiFiQuality NetworkMonitor::GetWiFiSignalQuality(const std::wstring& guid)
{
WiFiQuality result = WiFiQuality::Weak;
DWORD dwMaxClient = 2;
DWORD dwCurVersion = 0;
DWORD dwResult = 0;

unsigned int i, j;

PWLAN_INTERFACE_INFO_LIST pIfList = NULL;
PWLAN_INTERFACE_INFO pIfInfo = NULL;

PWLAN_AVAILABLE_NETWORK_LIST pBssList = NULL;
PWLAN_AVAILABLE_NETWORK pBssEntry = NULL;

int iRSSI = 0;

if (_wlanHandle == NULL)
{
dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &_wlanHandle);
if (dwResult != ERROR_SUCCESS)
{
std::cerr << "WlanOpenHandle failed with error: " << dwResult << std::endl;
return result;
}
dwResult = WlanRegisterNotification(_wlanHandle, WLAN_NOTIFICATION_SOURCE_ALL, TRUE, WLAN_NOTIFICATION_CALLBACK(OnNotificationCallback), NULL, NULL, NULL);
if (dwResult != ERROR_SUCCESS)
{
std::cerr << "WlanRegisterNotification failed with error: " << dwResult << std::endl;
return result;
}
}

dwResult = WlanEnumInterfaces(_wlanHandle, NULL, &pIfList);
if (dwResult != ERROR_SUCCESS)
{
std::cerr << "WlanEnumInterfaces failed with error: " << dwResult << std::endl;
return result;
}
for (i = 0; i < (int)pIfList->dwNumberOfItems; i++)
{
pIfInfo = (WLAN_INTERFACE_INFO*)&pIfList->InterfaceInfo[i];
if (guid != GUIDToString(pIfInfo->InterfaceGuid) || pIfInfo->isState != wlan_interface_state_connected)
{
continue;
}

dwResult = WlanGetAvailableNetworkList(_wlanHandle,
&pIfInfo->InterfaceGuid,
0,
NULL,
&pBssList);

if (dwResult != ERROR_SUCCESS)
{
std::cerr << "WlanGetAvailableNetworkList failed with error:" << dwResult << std::endl;
return result;
}
for (j = 0; j < pBssList->dwNumberOfItems; j++)
{
pBssEntry = (WLAN_AVAILABLE_NETWORK*)&pBssList->Network[j];

if (pBssEntry->bNetworkConnectable && (pBssEntry->dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED))
{
if (pBssEntry->wlanSignalQuality == 0)
iRSSI = -100;
else if (pBssEntry->wlanSignalQuality == 100)
iRSSI = -50;
else
iRSSI = -100 + (pBssEntry->wlanSignalQuality / 2);

std::cout << "Signal Quality:\t " << pBssEntry->wlanSignalQuality << " (RSSI: " << iRSSI << " dBm)" << std::endl;

result = iRSSI < -70 ? WiFiQuality::Weak :
iRSSI < -60 ? WiFiQuality::Fair :
iRSSI < -50 ? WiFiQuality::Good : WiFiQuality::Excellent;
}
}
}
if (pBssList != NULL)
{
WlanFreeMemory(pBssList);
pBssList = NULL;
}

if (pIfList != NULL)
{
WlanFreeMemory(pIfList);
pIfList = NULL;
}
return result;
}

void NetworkMonitor::OnWiFiQualityChange(const GUID& guid)
{
auto nowQuality = GetWiFiSignalQuality(GUIDToString(guid));
std::cout << "WiFi signal quality now : " << nowQuality << std::endl;
ShowNetworkStatus();
}

void NetworkMonitor::ShowNetworkStatus()
{
NetworkType type;
WiFiQuality quality;
auto connections = GetNetworkConnections();
if (connections.empty())
{
type = NetworkType::NotNetwork;
}
else
{
type = connections.front().type;
if (type == NetworkType::Wlan)
{
quality = GetWiFiSignalQuality(connections.front().guid);
}
}

std::cout << "====== Notify ======" << std::endl;
std::cout << "* Type : " << (type == NetworkType::NotNetwork ? "NetworkError" : type == NetworkType::Ethernet ? "Ethernet" : "WiFi") << std::endl;
if (type == NetworkType::Wlan)
{
std::cout << "* Signal : " << quality + 1 << std::endl;
}
std::cout << std::endl;
}

int main()
{
InstanceOfNetworkMonitor()->ShowNetworkStatus();
while (true) std::this_thread::sleep_for(std::chrono::hours(10));
return 0;
}

使用示例2

监控网络连接状态

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
#include <netlistmgr.h>
#include "sp_log.h"
#include <atomic>
#include <thread>
#include <mutex>
#include <string>
#include <vector>
#include <netcon.h>
#include <Shlwapi.h>
#include <TLHELP32.H>
#include <UserEnv.h>
#include <iphlpapi.h>
#pragma comment(lib,"shlwapi.lib")
#pragma comment(lib,"Iphlpapi.lib")

class CNetworkListManagerEvent : public INetworkListManagerEvents
{
public:
CNetworkListManagerEvent(std::function<void(bool)> netChangedHandler)
: m_ref(1)
, netChangedHandler_(netChangedHandler)
{

}

~CNetworkListManagerEvent()
{

}

HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject)
{
HRESULT Result = S_OK;
if (IsEqualIID(riid, IID_IUnknown))
{
*ppvObject = (IUnknown*)this;
}
else if (IsEqualIID(riid, IID_INetworkListManagerEvents))
{
*ppvObject = (INetworkListManagerEvents*)this;
}
else
{
Result = E_NOINTERFACE;
}

return Result;
}

ULONG STDMETHODCALLTYPE AddRef()
{
return (ULONG)InterlockedIncrement(&m_ref);
}

ULONG STDMETHODCALLTYPE Release()
{
LONG Result = InterlockedDecrement(&m_ref);
if (Result == 0)
delete this;
return (ULONG)Result;
}

virtual HRESULT STDMETHODCALLTYPE ConnectivityChanged(
/* [in] */ NLM_CONNECTIVITY newConnectivity)
{
if (newConnectivity == NLM_CONNECTIVITY_DISCONNECTED)
{
SP_DEV_LOGT("internet status changed. connect closed");

// 网络断开
netChangedHandler_(false);
}
else if ((newConnectivity & NLM_CONNECTIVITY_IPV4_INTERNET) || (newConnectivity & NLM_CONNECTIVITY_IPV6_INTERNET))
{
SP_DEV_LOGT("internet status changed. connect success");

// 网络连接成功
netChangedHandler_(true);
}
return S_OK;
}

private:
LONG m_ref;
std::function<void(bool)> netChangedHandler_;
};


class CNetworkMonitor
{
public:
CNetworkMonitor() {};
~CNetworkMonitor() {};

private:
// 监控网络状态变化
static void InitNetworkMonitor()
{
SP_DEV_LOGT("InitNetworkMonitor");

bool bSuccess = false;
CoInitialize(NULL);
//
// 通过NLA接口获取网络状态
//
IUnknown* pUnknown = NULL;
HRESULT Result = CoCreateInstance(CLSID_NetworkListManager, NULL, CLSCTX_ALL, IID_IUnknown, (void**)&pUnknown);
if (SUCCEEDED(Result))
{
INetworkListManager* pNetworkListManager = NULL;
Result = pUnknown->QueryInterface(IID_INetworkListManager, (void**)&pNetworkListManager);
if (SUCCEEDED(Result))
{
VARIANT_BOOL IsConnect = VARIANT_FALSE;
Result = pNetworkListManager->get_IsConnectedToInternet(&IsConnect);
if (SUCCEEDED(Result))
{
printf("connect to internet:%s", IsConnect == VARIANT_TRUE ? "TRUE" : "FALSE");
}

IConnectionPointContainer* pCPContainer = NULL;
Result = pNetworkListManager->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPContainer);
if (SUCCEEDED(Result))
{
IConnectionPoint* pConnectPoint = NULL;
Result = pCPContainer->FindConnectionPoint(IID_INetworkListManagerEvents, &pConnectPoint);
if (SUCCEEDED(Result))
{
DWORD Cookie = NULL;

CNetworkMonitor networkMonitor;
std::function<void(bool)> monitorFunc = std::bind(&CNetworkMonitor::NetworkStatusChangedCallback, networkMonitor, std::placeholders::_1);
CNetworkListManagerEvent* pNetEvent = new(std::nothrow) CNetworkListManagerEvent(monitorFunc);
if (pNetEvent)
{
Result = pConnectPoint->Advise((IUnknown*)pNetEvent, &Cookie);
if (SUCCEEDED(Result))
{
printf("InitNetworkMonitor success");
bSuccess = true;

MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);

if (msg.message == WM_QUIT)
{
break;
}
}

pConnectPoint->Unadvise(Cookie);
pConnectPoint->Release();
}
}
}
pCPContainer->Release();
}
pNetworkListManager->Release();
}
pUnknown->Release();
}
CoUninitialize();
}

void NetworkStatusChangedCallback(bool status)
{
g_bNetWorkOnline = status;
if (status)
{
if (g_sp_trust_model.get())
{
if (g_sp_trust_model->IsOnline())
{
//休眠唤醒后网络连接成功,自动发送一次心跳
printf("Sleep wakes up and automatically triggers a heartbeat");
}
else
{
printf("No login, will not rebuild trust nc");
}
}
else
{
printf("rebuild trust nc - g_sp_trust_model is null");
}
}
}

public:
void StartMonitor()
{
std::thread monitorThread(&InitNetworkMonitor);
monitorThread.detach();
}
};

【网络编程】【Windows】监控指定网卡事件
https://hodlyounger.github.io/A_OS/Windows/网络helper/【网络编程】(超详细)监控网卡事件2/
作者
mingming
发布于
2023年10月27日
许可协议