如何从Windows应用程序中检测禁用的网络接口连接?

15
我想知道接口何时被禁用。
如果我进入Windows管理器并禁用其中1个已启用的连接,GetIfTable()仅返回有关1个接口的状态,它不再看到已断开的接口。(返回1个表)
如何获取某些内容返回被禁用的接口仍然存在但目前已禁用?
谢谢。
链接:http://msdn.microsoft.com/en-us/library/aa365943%28VS.85%29.aspx
6个回答

8

我认为你只需要读取注册表。

例如,以下是从网上找到的代码片段,展示了注册表应该是什么样子:

[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

这里的哪个字段是启用/禁用状态? - T.T.T.
1
我不记得,而且我也不在任何Windows电脑附近。希望你能找到有关这个指针的更多信息……现在对此感到抱歉。 - sehe
1
我认为根据PnpInstanceId的信息,您应该在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\PCI中找到驱动程序信息,然后您应该看到ConfigFlags键。如果设置为0,则启用NIC卡,如果设置为1,则禁用。 - Zuljin
我记得不是很清楚,但我认为首先你必须调用RegOpenKeyEx函数来获取键,然后使用该键调用RegQueryValueEx来获取特定值。请查看SO旧问题和MSDN文档,了解如何准确调用这些函数http://msdn.microsoft.com/en-us/library/ms724875(v=vs.85).aspx - Zuljin

8
如何使用netcon.h中的接口,可以参考这个例子。该示例中的代码可以通过编程方式启用和禁用接口,但我进行了一些修改,以便您可以查询状态:
#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; 
}

循环中未使用'done'变量-这是复制/粘贴问题 :-) - Simon Mourier

6
另一种选择是使用 Win32_NetworkAdapter WMI类,检查NetConnectionStatusNetEnabled属性。

如果您发现此WMI类为您提供所需的状态,请注意,WMI确实为您提供“轮询服务”,以定期检查值是否已更改。请查看[__InstanceModificationEvent](http://technet.microsoft.com/en-us/library/ee156572.aspx)(但如果您将其构建到应用程序中,请小心,因为尽管表面上很简单,但您可能会发现WMI轮询是重量级的。) - Daryn

4

IP_ADAPTER_ADDRESSES结构体包含OperStatus成员。

请参见MSDN文档

我认为它可以用于检测已禁用的NIC,但我没有尝试过。

下面是一个测试代码:

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的信息返回...... - T.T.T.

3

3

命令行:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接