开发者

How could I get or change the IP address of a disconnected NIC in Windows?

开发者 https://www.devze.com 2023-03-17 20:54 出处:网络
I have configured the IP address for a N开发者_StackOverflow社区IC successfully in Windows7. But after pulling out the net cable, I can\'t get the IP address from API and ipconfig, but I can view it i

I have configured the IP address for a N开发者_StackOverflow社区IC successfully in Windows7. But after pulling out the net cable, I can't get the IP address from API and ipconfig, but I can view it in "Network Connections". And if I insert the cable again, then I can get the address once more.

How could I get or change the IP address of a NIC, when the NIC is disconnected? I have used "GetAdaptersInfo" "GetIpAddrTable" or WMI class. All above method return 0.0.0.0 ipaddress for such NIC.

My platform is Windows7, and I wish the method can work for other Windows platforms.

Thanks!


The IP address isn't a property inherent to the NIC. The instant it becomes disconnected, it loses its IP. The IP is assigned by either a DHCP server or statically by your OS when there is actually a connection.


To get the IP from a disconnected NIC, try using netsh interface dump, for example:

netsh interface ipv4 dump name="Wireless Network Connection"

The ouput is like:

#----------------------------------
# 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


Some people suggested me to change a registry key, which will turn off media detection.

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

Type:  REG_DWORD
Value: 1

I have tested this method but it still returns 0.0.0.0, but I can read unpluged NIC's IP address from reg:

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


As sshannin noted, the IP is only assigned, if the interface is connected. If you don't want to parse the output of netsh (as dmitry noted), you could check for settings in the registry in HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<GUID>

The IP address(es) which will get assigned to the interface are in the IPaddress REG_MULTI_SZ value, which is string list for several IPs.

Also the information about DHCP may be invalid if no cable is connected, so check the DisableDhcpOnConnect.

The following code outputs the first IP address of each network adapter found (no complete error handling):

#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;
  }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号