【问题标题】:How do I detect a disabled Network Interface Connection from a Windows application?如何从 Windows 应用程序检测禁用的网络接口连接?
【发布时间】:2011-08-20 12:17:38
【问题描述】:

我想知道某个接口何时被禁用。

如果我进入 Windows 管理器并禁用 2 个启用的连接之一,GetIfTable() 只返回关于 1 个接口的状态,它不再看到断开的接口。 (返回 1 个表)

我如何才能返回已禁用的接口仍然存在当前已禁用?

谢谢。

http://msdn.microsoft.com/en-us/library/aa365943%28VS.85%29.aspx

【问题讨论】:

    标签: c++ windows winapi networking wmi


    【解决方案1】:

    命令行:

    wmic NIC where(ConfigManagerErrorCode=22)get Description,Index,NetConnectionID,PNPDeviceID
    

    输出:

    Description                            Index  NetConnectionID                            PNPDeviceID
    Broadcom 802.11g Network Adapter       8      WiFi                                       PCI\VEN_14E4&DEV_4320&SUBSYS_041814E4&REV_03\4&31B6CD7&0&00F0
    1394 Net Adapter                       13     1394                                       V1394\NIC1394\1B9E0F31E8C00
    TAP-Win32 Adapter V9                   14     Steganos Internet Anonym 2012 VPN Adapter  ROOT\NET\0000
    VirtualBox Host-Only Ethernet Adapter  24     VirtualBox Host-Only Network               ROOT\NET\0001
    

    【讨论】:

      【解决方案2】:

      如何使用netcon.h 中的接口,如this example 所示?该示例中的代码以编程方式启用和禁用接口,但我进行了一些修改,以便您可以查询状态:

      #include <netcon.h>
      // wszName is the name of the connection as appears in Network Connections folder
      // set bEnable to true to enable and to false to disable
      bool GetConnectionStatus(LPCWSTR wszName, bool *status)
      {
          bool result = false;
          if (!status)
              return false;
          typedef void (__stdcall * LPNcFreeNetconProperties)(NETCON_PROPERTIES* pProps);
          HMODULE hmod = LoadLibrary("netshell.dll");
          if (!hmod) 
              return false; 
          LPNcFreeNetconProperties NcFreeNetconProperties = 
              (LPNcFreeNetconProperties)GetProcAddress(hmod, "NcFreeNetconProperties"); 
          if (!NcFreeNetconProperties ) 
              return false; 
      
          INetConnectionManager * pMan = 0; 
      
          HRESULT hres = CoCreateInstance(CLSID_ConnectionManager, 
                                          0, 
                                          CLSCTX_ALL, 
                                          __uuidof(INetConnectionManager), 
                                          (void**)&pMan); 
          if (SUCCEEDED(hres)) 
          { 
              IEnumNetConnection * pEnum = 0;  
              hres = pMan->EnumConnections(NCME_DEFAULT, &pEnum); 
              if (SUCCEEDED(hres)) 
              { 
                  INetConnection * pCon = 0; 
                  ULONG count; 
                  while (pEnum->Next(1, &pCon, &count) == S_OK && !done) 
                  { 
                      NETCON_PROPERTIES * pProps = 0; 
                      hres = pCon->GetProperties(&pProps); 
                      if (SUCCEEDED(hres)) 
                      { 
                          if (wcscmp(pProps->pszwName,wszName) == 0) 
                          { 
                              *status = pProps->Status == NCS_CONNECTED;
                          } 
                          NcFreeNetconProperties(pProps); 
                      } 
                      pCon->Release(); 
                  } 
                  pEnum->Release(); 
              } 
              pMan->Release(); 
          } 
      
          FreeLibrary(hmod); 
          return result; 
      }
      

      【讨论】:

      • 循环中未使用“完成”变量 - 复制/粘贴问题 :-)
      【解决方案3】:

      根据this CodeGuru forum message,您可以查询 WMI 以获取此信息(那里提供了 C# 代码)。

      要使用 C++ 查询 WMI,请参阅以下两个链接:

      【讨论】:

        【解决方案4】:

        另一个选项是使用 Win32_NetworkAdapter WMI 类,检查 NetConnectionStatusNetEnabled 属性。

        【讨论】:

        • 如果您发现此 WMI 类为您提供了所需的状态,请注意 WMI 确实为您提供了“轮询服务”以定期检查值是否已更改。看看__InstanceModificationEvent(但如果您将其构建到应用程序中,请小心,因为您可能会发现 WMI 轮询是重量级的,尽管它看起来很简单。)
        【解决方案5】:

        IP_ADAPTER_ADDRESSES 结构包含一个 OperStatus 成员。 见MSDN documentation

        我认为它可以用来检测禁用的网卡。我没试过。

        这是一个测试代码:

        ULONG nFlags= 0;
        if (WINVER>=0x0600)                              // flag supported in Vista and later
            nFlags= 0x0100;                              // GAA_FLAG_INCLUDE_ALL_INTERFACES
        
        // during system initialization, GetAdaptersAddresses may return ERROR_BUFFER_OVERFLOW and supply nLen,
        // but in a subsequent call it may return ERROR_BUFFER_OVERFLOW and supply greater nLen !
        ULONG nLen= sizeof (IP_ADAPTER_ADDRESSES);
        BYTE* pBuf= NULL;
        DWORD nErr= 0   ;
        do
        {
            delete[] pBuf;
            pBuf= new BYTE[nLen];
            nErr= ::GetAdaptersAddresses(AF_INET, nFlags, NULL, (IP_ADAPTER_ADDRESSES*&)pBuf, &nLen);
        }
        while (ERROR_BUFFER_OVERFLOW == nErr);
        
        if (NO_ERROR != nErr)
        {
            delete[] pBuf;
        
            TCHAR czErr[300]= _T("GetAdaptersAddresses failed. ");
            REPORT(REP_ERROR, _T("GetAdapterInfo"), GetSysErrStr(nErr, czErr, 300));
            return false;
        }
        
        const IP_ADAPTER_ADDRESSES* pAdaptersAddresses= (IP_ADAPTER_ADDRESSES*&)pBuf;
        
        while (pAdaptersAddresses) // for each adapter
        {
            TCHAR czAdapterName [500]; str_cpy(czAdapterName , 500, pAdaptersAddresses->AdapterName );
            TCHAR czDesc        [500]; str_cpy(czDesc        , 500, pAdaptersAddresses->Description );
            TCHAR czFriendlyName[500]; str_cpy(czFriendlyName, 500, pAdaptersAddresses->FriendlyName);
        
            const IF_OPER_STATUS& Stat= pAdaptersAddresses->OperStatus; // 1:up, 2:down...
        
            ...
        
            pAdaptersAddresses= pAdaptersAddresses->Next;
        }
        

        【讨论】:

        • 不幸的是,这里没有任何内容表明已启用。我尝试了这种方法,它的行为与 GetIfTable() 相同,仅返回一个 nic 的状态(链表)......我希望至少能通过 IF_OPER_STATUS 获取信息......
        【解决方案6】:

        我认为您只需要阅读注册表即可。

        例如,这是在网上找到的一个 sn-p,它应该是什么样子的:

        [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\{1E6AF554-25FF-40FC-9CEE-EB899472C5A3}\Connection]
        "PnpInstanceID"="PCI\\VEN_14E4&DEV_1696&SUBSYS_12BC103C&REV_03\\4&3A321F38&0&10F0"
        "MediaSubType"=dword:00000001
        "Name"="Lan Name"
        "ShowIcon"=dword:00000000
        "IpCheckingEnabled"=dword:00000001
        
        [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\{1E6AF554-25FF-40FC-9CEE-EB899472C5A3}\Connection]
        "PnpInstanceID"="PCI\\VEN_14E4&DEV_1696&SUBSYS_12BC103C&REV_03\\4&3A321F38&0&10F0"
        "MediaSubType"=dword:00000001
        "Name"="Lan Name"
        "ShowIcon"=dword:00000000
        "IpCheckingEnabled"=dword:00000001
        

        【讨论】:

        • 这里哪个字段是dis/enabled状态?
        • 我从记忆中不知道,而且我不在任何 Windows PC 附近。我希望您能找到有关此指针的更多信息...暂时先说一下
        • 我认为基于来自 PnpInstanceId 的信息,您应该在 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\PCI 中找到驱动程序信息,并且在那里您应该看到 ConfigFlags 键。如果设置为 0 则启用网卡,如果设置为 1 则禁用。
        • 我不太记得了,但我认为首先你必须调用 RegOpenKeyEx 函数来获取密钥,然后使用该密钥你必须调用 RegQueryValueEx 来获取特定值。请查看 SO old questions 和 MSDN 文档如何准确调用这些函数msdn.microsoft.com/en-us/library/ms724875(v=vs.85).aspx
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-23
        • 1970-01-01
        • 2021-09-29
        相关资源
        最近更新 更多