如何在Windows中获取或更改已断开连接的NIC的IP地址?

时间:2011-07-06 09:53:05

标签: windows visual-c++ networking network-programming wmi

我已在Windows7中成功配置了NIC的IP地址。但拔出网线后,我无法从API和ipconfig获取IP地址,但我可以在“网络连接”中查看。如果我再次插入电缆,那么我可以再次获得该地址。

当NIC断开连接时,如何获取或更改NIC的IP地址?我使用过“GetAdaptersInfo”“GetIpAddrTable”或WMI类。以上所有方法都为此类NIC返回0.0.0.0 ipaddress。

我的平台是Windows7,我希望该方法适用于其他Windows平台。

谢谢!

4 个答案:

答案 0 :(得分:1)

有人建议我更改注册表项,这将关闭媒体检测。

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Parameters\DisableDHCPMediaSense

Type:  REG_DWORD
Value: 1

我已经测试了这个方法,但它仍然返回0.0.0.0,但我可以从reg中读取未插入的NIC的IP地址:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\[NIC_GUID]}\Parameters\Tcpip]
EnableDHCP
IPAddress
SubnetMask
DefaultGateway

答案 1 :(得分:1)

IP地址不是NIC固有的属性。它变为断开连接的瞬间就失去了它的IP。 IP由DHCP服务器分配,或者在实际连接时由您的OS静态分配。

答案 2 :(得分:1)

要从断开连接的NIC获取IP,请尝试使用netsh interface dump,例如:

netsh interface ipv4 dump name="Wireless Network Connection"

输出就像:

#----------------------------------
# IPv4 Configuration
# ----------------------------------

pushd interface ipv4

reset
set global icmpredirects=enabled
add address name="Wireless Network Connection" address=192.168.229.2 mask=255.255.255.0


popd
# End of IPv4 configuration

答案 3 :(得分:0)

如sshannin所述,仅在连接接口的情况下分配IP。如果您不想解析netsh的输出(如dmitry所述),则可以在以下位置检查注册表中的设置: HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<GUID>

要分配给接口的IP地址在IPaddress REG_MULTI_SZ值中,该值是多个IP的字符串列表。

如果没有连接电缆,则有关DHCP的信息可能无效,因此请检查DisableDhcpOnConnect

以下代码输出找到的每个网络适配器的第一个IP地址(没有完整的错误处理):

#define WINNT 0x501
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <sstream>
#include <list>
#include <map>
#include <algorithm>
#include <iomanip>

#include <ws2ipdef.h>
#include <iphlpapi.h>
#undef __IPHLPAPI_H__
#include <winternl.h>
#include <netioapi.h>   // In my SDK iphlpapi.h does not include netioapi.h !!!


#pragma comment (lib, "ws2_32")
#pragma comment (lib, "iphlpapi")

using namespace std;

class IP
{
public:
  IP(unsigned long _ip = 0) : ip(ntohl(_ip)) {}

  unsigned long ip;
};

wostream &operator<<(wostream &str, IP ip)
{
  wostringstream o; o << ((ip.ip&0xff000000)>>24) << L"." << ((ip.ip&0xff0000)>>16) << L"." << ((ip.ip&0xff00)>>8) << L"." << (ip.ip&0xff);
  return str << o.str();
}

typedef DWORD (__stdcall *fnGetIfTable2)(PMIB_IF_TABLE2*);

struct AdapterInfo
{
  enum eCable {
    connected,
    disconnected,
    unknown
  } cable;
  wstring FriendlyName;
  wstring Description;
  IP IpAddr;
  IP Subnet;
  bool dhcp;
  unsigned char MAC[MAX_ADAPTER_ADDRESS_LENGTH];
  ULONG64 speed;

  AdapterInfo() : speed(0), cable(unknown) { memset(MAC, 0, sizeof(MAC)); };
};

map<unsigned long, AdapterInfo> Adapters;

int main()
{
  WSADATA wsaData;
  WSAStartup(MAKEWORD( 2, 2 ), &wsaData);

  // 1. Gather the relevant interfaces (no loopback or IPv6)
  // -------------------------------------------------------
  list<unsigned long> Indices;
  PIP_INTERFACE_INFO pIfTable = 0;
  ULONG dwIfTableSize = 0;
  while (GetInterfaceInfo(pIfTable, &dwIfTableSize) == ERROR_INSUFFICIENT_BUFFER) {
    if (pIfTable)
      free(pIfTable);
    pIfTable = (PIP_INTERFACE_INFO)malloc(dwIfTableSize);
  }

  for (int i= 0; i < pIfTable->NumAdapters; ++i)
    Indices.push_back(pIfTable->Adapter[i].Index);
  free(pIfTable);


  // 2. Get the IP address (only one per adapter)
  // --------------------------------------------
  PMIB_IPADDRTABLE pIPAddrTable = 0;
  DWORD dwSize = 0;
  while (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
    if (pIPAddrTable)
      free( pIPAddrTable );
    pIPAddrTable = (PMIB_IPADDRTABLE) malloc( dwSize );
  }

  for (unsigned i = 0; i<pIPAddrTable->dwNumEntries; ++i)
  {
    if (find(Indices.begin(), Indices.end(), pIPAddrTable->table[i].dwIndex) == Indices.end())
      continue;   // Any interface which is not relevant (probably loopback)
    Adapters[pIPAddrTable->table[i].dwIndex].IpAddr = pIPAddrTable->table[i].dwAddr;
    Adapters[pIPAddrTable->table[i].dwIndex].Subnet = pIPAddrTable->table[i].dwMask;
  }


  // 3. Get the name of the interface
  // --------------------------------
  IP_ADAPTER_ADDRESSES *AdapterAddresses = 0;
  ULONG OutBufferLength = 0;
   while (GetAdaptersAddresses(AF_INET, 0,NULL, AdapterAddresses, &OutBufferLength) == ERROR_BUFFER_OVERFLOW) {
    if (AdapterAddresses)
      free(AdapterAddresses);
    AdapterAddresses = (PIP_ADAPTER_ADDRESSES) malloc(OutBufferLength);
  }

  PIP_ADAPTER_ADDRESSES AdapterList = AdapterAddresses;
  while (AdapterList) {
    if (find(Indices.begin(), Indices.end(), AdapterList->IfIndex) != Indices.end())
    {
      Adapters[AdapterList->IfIndex].FriendlyName = AdapterList->FriendlyName;
      Adapters[AdapterList->IfIndex].Description = AdapterList->Description;
      Adapters[AdapterList->IfIndex].dhcp = ((AdapterList->Flags&IP_ADAPTER_DHCP_ENABLED)!=0);
      Adapters[AdapterList->IfIndex].speed = min(AdapterList->TransmitLinkSpeed, AdapterList->ReceiveLinkSpeed);
      if (Adapters[AdapterList->IfIndex].speed == -1)
        Adapters[AdapterList->IfIndex].speed = 0;
      memcpy(Adapters[AdapterList->IfIndex].MAC, AdapterList->PhysicalAddress, min(AdapterList->PhysicalAddressLength, MAX_ADAPTER_ADDRESS_LENGTH));
    }
    AdapterList = AdapterList->Next;
  }

  // 4. Check if cable connected
  fnGetIfTable2 pGetIfTable2 = 0;

  HMODULE hModule = LoadLibraryA("Iphlpapi");
  if (hModule)
  {
    pGetIfTable2 = (fnGetIfTable2)GetProcAddress(hModule,"GetIfTable2");
    FreeLibrary(hModule);
  }

  if (pGetIfTable2)
  {
    PMIB_IF_TABLE2 table;
    if (pGetIfTable2(&table) == NO_ERROR)
    {
      for (ULONG i = 0; i < table->NumEntries; ++i)
      {
        if (Adapters.find(table->Table[i].InterfaceIndex) != Adapters.end())
        {
          switch(table->Table[i].MediaConnectState)
          {
            case MediaConnectStateUnknown:      Adapters[table->Table[i].InterfaceIndex].cable = AdapterInfo::unknown; break;
            case MediaConnectStateConnected:    Adapters[table->Table[i].InterfaceIndex].cable = AdapterInfo::connected; break;
            case MediaConnectStateDisconnected: Adapters[table->Table[i].InterfaceIndex].cable = AdapterInfo::disconnected;
                                                if (Adapters[table->Table[i].InterfaceIndex].IpAddr.ip == 0 && 
                                                   !Adapters[table->Table[i].InterfaceIndex].dhcp)
                                                {
                                                  // Check Registry for the IP of the unconnected NIC
                                                  GUID *pGuid = &table->Table[i].InterfaceGuid;
                                                  char sKey[256];
                                                  sprintf(sKey, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
                                                    pGuid->Data1, pGuid->Data2, pGuid->Data3,
                                                    pGuid->Data4[0], pGuid->Data4[1], pGuid->Data4[2], pGuid->Data4[3], pGuid->Data4[4], pGuid->Data4[5], pGuid->Data4[6], pGuid->Data4[7]);

                                                  HKEY hKey;
                                                  LONG res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, sKey, 0, KEY_QUERY_VALUE|KEY_WOW64_64KEY, &hKey);
                                                  if (res == ERROR_SUCCESS)
                                                  {
                                                    if (Adapters[table->Table[i].InterfaceIndex].dhcp)
                                                    {
                                                      DWORD type, disableDHCP, size = sizeof(disableDHCP);
                                                      DWORD res = RegGetValueA(hKey,"", "DisableDhcpOnConnect", RRF_RT_REG_DWORD, &type, &disableDHCP, &size);
                                                      if (res == ERROR_SUCCESS && type == REG_DWORD)
                                                        Adapters[table->Table[i].InterfaceIndex].dhcp = disableDHCP == 0;
                                                    }

                                                    if (!Adapters[table->Table[i].InterfaceIndex].dhcp)
                                                    {
                                                      char IPAddress[512], SubnetMask[512];
                                                      DWORD type, size1 = sizeof(IPAddress), size2 = sizeof(SubnetMask);
                                                      DWORD res = RegGetValueA(hKey,"", "IPAddress", RRF_RT_REG_MULTI_SZ, &type, IPAddress, &size1);
                                                      if (res == ERROR_SUCCESS && type == REG_MULTI_SZ)
                                                      {
                                                        res = RegGetValueA(hKey,"", "SubnetMask", RRF_RT_REG_MULTI_SZ, &type, SubnetMask, &size2);
                                                        if (res == ERROR_SUCCESS && type == REG_MULTI_SZ)
                                                        {
                                                          Adapters[table->Table[i].InterfaceIndex].IpAddr = IP(inet_addr(IPAddress)); // String list, taking first element
                                                          Adapters[table->Table[i].InterfaceIndex].Subnet = IP(inet_addr(SubnetMask)); // String list, taking first element
                                                        }
                                                      }
                                                    }
                                                    RegCloseKey(hKey);
                                                  }
                                                }
                                                break;
          }
        }
      }
    }
  }

  // Output everything...
  // --------------------
  
  map<unsigned long, AdapterInfo>::iterator it = Adapters.begin(), end = Adapters.end();
  while (it != end)
  {
    wcout << L"Adapter \"" << it->second.FriendlyName << L"\"\n";
    wcout << L"  DHCP:    " << (it->second.dhcp?L"yes":L"no") << endl;
    if (it->second.IpAddr.ip)
      wcout << L"  IP :     " << it->second.IpAddr << endl;
    if (it->second.Subnet.ip)
      wcout << L"  Subnet:  " << it->second.Subnet << endl;

    if (it->second.MAC[0] || it->second.MAC[1] || it->second.MAC[2] || it->second.MAC[3] || it->second.MAC[4] || it->second.MAC[5])
      wcout << L"  MAC:     " << hex << setfill(L'0') << setw(2) << (unsigned)it->second.MAC[0] << L"-" << setw(2) << (unsigned)it->second.MAC[1] << L"-" << setw(2) << (unsigned)it->second.MAC[2] << L"-" << setw(2) << (unsigned)it->second.MAC[3] << L"-" << setw(2) << (unsigned)it->second.MAC[4] << L"-" << setw(2) << (unsigned)it->second.MAC[5] << dec << endl;
    if (it->second.speed)
      wcout << L"  Speed:   " << it->second.speed << endl;
    if (!it->second.Description.empty())
      wcout << L"  Descr.   \"" << it->second.Description << L"\"" << endl;

    if (it->second.cable != AdapterInfo::unknown)
    {
      switch(it->second.cable)
      {
        case AdapterInfo::connected:    wcout << "  Cable:   connected"; break;
        case AdapterInfo::disconnected: wcout << "  Cable:   disconnected"; break;
      }
    }

    wcout << endl;

    ++it;
  }
}