[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 连接条件模拟。

使用参考:

...
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 接口的指针。

使用参考:

...
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 可以建立连接点对象与客户端接收器之间的连接。也就是可以通过此接口实现网络事件的监控。

使用参考:

...
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的网络质量

#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

监控网络连接状态

#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();
	}
};