【问题标题】:Event sent by Windows when connected to internet连接到 Internet 时由 Windows 发送的事件
【发布时间】:2021-04-28 06:32:53
【问题描述】:

我需要在我的程序中知道何时恢复到互联网的连接。

实际上我可以检查它是否与类似的东西有关

CComPtr<INetworkListManager> pNLM;
HRESULT hr = CoCreateInstance(CLSID_NetworkListManager, NULL, CLSCTX_ALL, __uuidof(INetworkListManager), (LPVOID*)&pNLM);
if (SUCCEEDED(hr))
{
    VARIANT_BOOL isConnected;
    pNLM->get_IsConnectedToInternet(&isConnected);
    if (isConnected == VARIANT_TRUE)

但我找不到一个很好的方法来通知连接已恢复。 对我来说,投票不是一个好方法。

我找到了::NotifyAddrChange(),但只要在将 IPv4 地址映射到接口的表中发生更改,就会触发此问题。

建立连接时是否发送特定事件?

【问题讨论】:

  • 您可能需要实现并注册INetworkEvents 接口。虽然实现接口看起来很简单,但我不知道你会如何注册它。
  • 还是INetworkListManagerEvents接口?无论如何,我不知道如何注册您的回调,而且 - 对所有其他 COM 文档都是如此 - 从字面上看,nothing 描述了系统的整体结构。像Network List Manager Architecture 这样的无用版本将有很长的路要走。
  • 我不知道我的同事过去这样做了,所以我从他那里得到了代码。我会尽快添加答案,因为对其他人有用,MS 没有关于它的文档

标签: c++ windows events networking


【解决方案1】:

感谢我的一位同事,我有答案了。

这是将调用回调的类

#include "Event.h"

Event::Event(const std::function<void()>& cb)
    : methodTobeCalled(cb)
{
}

HRESULT Event::NetworkConnectionConnectivityChanged(GUID, NLM_CONNECTIVITY)
{
    if (methodTobeCalled)
        methodTobeCalled();

    return S_OK;
}

HRESULT Event::NetworkConnectionPropertyChanged(GUID, NLM_CONNECTION_PROPERTY_CHANGE)
{
    return S_OK;
}

STDMETHODIMP Event::QueryInterface(REFIID refIID, void** pIFace)
{
    HRESULT hr = S_OK;
    *pIFace = nullptr;
    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 Event::AddRef(void)
{
    return static_cast<ULONG>(InterlockedIncrement(&m_ref));
}

ULONG Event::Release(void)
{
    LONG Result = InterlockedDecrement(&m_ref);
    return static_cast<ULONG>(Result);
}

在主类的ctor中(这里没有错误处理):

::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
::CoCreateInstance(CLSID_NetworkListManager, nullptr, CLSCTX_ALL, IID_INetworkListManager, (LPVOID *)&m_pNLM);
m_pNLM->QueryInterface(IID_IConnectionPointContainer, (void **)&m_pCpc);
m_pCpc->FindConnectionPoint(IID_INetworkConnectionEvents, &m_pConnectionPoint);
m_event = std::make_unique<NetworkEvent>(std::bind(&MainClass::methodTobeCalled, this));
hr = m_pConnectionPoint->Advise((IUnknown *)m_event.get(), &m_cookie);

需要的变量:

std::unique_ptr<NetworkEvent> m_event;
DWORD m_cookie;
CComPtr<IConnectionPoint> m_pConnectionPoint;
CComPtr<INetworkListManager> m_pNLM;
CComPtr<IConnectionPointContainer> m_pCpc;

将在每个网络事件中调用的方法将是

MainClass::methodTobeCalled()

在这种方法中,可以检查连接是否可用。 O 可以检查 NetworkConnectionConnectivityChanged() 中的 NLM_CONNECTIVITY 标志

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-26
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
相关资源
最近更新 更多