65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.81/5 (13投票s)

2013年4月8日

CPOL

2分钟阅读

viewsIcon

61898

downloadIcon

3334

本文档解释了如何使用网络列表管理器服务来识别和检索 PC 连接到每个网络时的属性。

介绍 

示例应用程序枚举 PC 连接到的网络,并显示所选网络的一些属性。它还会监听连接状态,并在连接更改时进行更新。

背景 

网络列表管理器作为 Svchost.exe 上下文中的服务运行,并在计算机启动过程中启动。网络列表管理器服务维护一个可用网络和网络属性的表,应用程序通过网络列表管理器 API 检索这些信息。INetworkListManager 是我们用于与网络列表管理器服务通信以查询网络详细信息的接口。

注意:INetworkListManager 是在 Windows Vista 中引入的。

使用代码

示例应用程序是使用 Visual Studio 2012 开发的 MFC 对话框应用程序。INetworkListManagerCLSID_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;
}

© . All rights reserved.