使用网络列表管理器 (C++)






4.81/5 (13投票s)
本文档解释了如何使用网络列表管理器服务来识别和检索 PC 连接到每个网络时的属性。
介绍
示例应用程序枚举 PC 连接到的网络,并显示所选网络的一些属性。它还会监听连接状态,并在连接更改时进行更新。
背景
网络列表管理器作为 Svchost.exe 上下文中的服务运行,并在计算机启动过程中启动。网络列表管理器服务维护一个可用网络和网络属性的表,应用程序通过网络列表管理器 API 检索这些信息。INetworkListManager
是我们用于与网络列表管理器服务通信以查询网络详细信息的接口。
注意:INetworkListManager
是在 Windows Vista 中引入的。
使用代码
示例应用程序是使用 Visual Studio 2012 开发的 MFC 对话框应用程序。INetworkListManager
在 CLSID_NetworkListManager
CoClass 上实现。为了使用此接口,有必要创建 CLSID_NetworkListManager
COM 对象,如下所示。确保在进行这些调用之前调用了 CoInitialize()
。
CComPtr <INetworkListManager> m_pNLM;
m_pNLM.CoCreateInstance(CLSID_NetworkListManager);
创建 CLSID_NetworkListManager
对象后,您可以枚举所有已连接的网络,如下所示。
CComPtr<IEnumNetworks> pEnumNetworks;
if(SUCCEEDED(m_pNLM->GetNetworks(NLM_ENUM_NETWORK_CONNECTED, &pEnumNetworks)))
{
DWORD dwReturn = 0;
while(true)
{
CComPtr<INetwork> pNetwork;
hr = pEnumNetworks->Next(1, &pNetwork, &dwReturn);
if(hr == S_OK && dwReturn > 0)
{
Dump_NW_Info(pNetwork);
}
else
{
break;
}
}
}
INetwork
接口表示本地机器上的网络。它也可以表示具有相似网络签名的网络连接集合。您可以使用 INetwork
接口的 GET 方法获取网络的类别、连接类型、描述、域类型和名称。示例中的 Dump_NW_Info 收集所有这些信息。INetwork
接口有一个名为 get_IsConnectedToInternet
的属性,它指定网络是否具有互联网连接。
监听连接事件
INetworkListManagerEvents
是一个消息接收器接口,客户端实现该接口以获取与整体机器状态相关的事件。对高级事件(例如互联网连接)感兴趣的应用程序实现此接口。此接口继承自 IUnknown
接口,并且具有一种方法。
HRESULT STDMETHODCALLTYPE ConnectivityChanged( NLM_CONNECTIVITY NewConnectivity );
我们按如下方式实现 Sink 类
class CoNetworkEventHandler : public INetworkListManagerEvents
{
public:
CoNetworkEventHandler(void);
virtual ~CoNetworkEventHandler(void);
STDMETHODIMP QueryInterface (REFIID riid, void** pIFace);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
STDMETHODIMP ConnectivityChanged(NLM_CONNECTIVITY NewConnectivity);
private:
long m_lRefCnt;
DWORD m_dwCookie;
};
创建 Sink 对象后,我们可以按如下方式建立到连接点的连接
CoNetworkEventHandler * m_pSink;
LPUNKNOWN m_pUnkSink;
m_pSink = new CoNetworkEventHandler();
if (SUCCEEDED (m_pSink->QueryInterface(IID_IUnknown, (void**) &m_pUnkSink)))
{
AfxConnectionAdvise (m_pNLM, __uuidof(INetworkListManagerEvents),
m_pUnkSink, FALSE, &m_dwCookie);
}
发生网络事件时,将调用此回调函数。
HRESULT CoNetworkEventHandler::ConnectivityChanged( NLM_CONNECTIVITY NewConnectivity)
{
bool bInternet = false;
if((NewConnectivity & NLM_CONNECTIVITY_IPV4_INTERNET) ||
(NewConnectivity & NLM_CONNECTIVITY_IPV4_INTERNET))
{
bInternet = true;
}
PostMessage(AfxGetApp()->GetMainWnd()->m_hWnd, UM_NETWORK_NOTIFY,
(WPARAM) bInternet, 0);
return S_OK;
}