Finding IP Address Information



Finding IP Address Information

One of the biggest challenges of network programming is dealing with network configurations of individual workstations and servers. When sending data across the network, you often need to determine the IP network information for the system running your program. The Windows OS family offers many ways to determine IP configuration information, both manually and from within a program. This section demonstrates a few of the ways that you can use to determine IP configuration information both manually and within your C# programs.

Using ipconfig

The ipconfig program displays IP network information for each active network interface on the system. The default form of ipconfig displays basic information for each network device:

C:\>ipconfig
Windows NT IP Configuration
Ethernet adapter El90x1:
    IP Address. . . . . . . . . : 192.168.1.6
    Subnet Mask . . . . . . . . : 255.255.255.0
    Default Gateway . . . . . . : 192.168.1.1
PPP adapter NdisWan5:
    IP Address. . . . . . . . . : 0.0.0.0
    Subnet Mask . . . . . . . . : 0.0.0.0
    Default Gateway . . . . . . :
C:\>

Here, the ipconfig program found two network interfaces configured on the workstation. The first interface is an Ethernet card configured for a LAN with a static IP address assigned to the workstation. The second device is a PPP connection configured to use a modem in the workstation. Because the PPP connection obtains its IP information dynamically when the PPP session starts, the values set by default in the workstation are zeroed. When the PPP connection is enabled, the assigned IP information is displayed.

To obtain more detailed information about a device, use the /all switch for the ipconfig command, as shown here:

C:\>ipconfig /all
Windows NT IP Configuration
    Host Name . . . . . . . . . : shadrach.blum.lan
    DNS Servers . . . . . . . . : 192.168.1.1
                   192.168.1.2
                   192.168.1.3
    Node Type . . . . . . . . . : Broadcast
    NetBIOS Scope ID. . . . . . :
    IP Routing Enabled. . . . . : No
    WINS Proxy Enabled. . . . . : No
    NetBIOS Resolution Uses DNS : No
Ethernet adapter El90x1:
    Description . . . . . . . . : 3Com EtherLink PCI
    Physical Address. . . . . . : 00-50-DA-10-78-67
    DHCP Enabled. . . . . . . . : No
    IP Address. . . . . . . . . : 192.168.1.6
    Subnet Mask . . . . . . . . : 255.255.255.0
    Default Gateway . . . . . . : 192.168.1.1
PPP adapter NdisWan5:
Description . . . . . . . . : NdisWan Adapter
    Physical Address. . . . . . : 00-00-00-00-00-00
    DHCP Enabled. . . . . . . . : No
    IP Address. . . . . . . . . : 0.0.0.0
    Subnet Mask . . . . . . . . : 0.0.0.0
    Default Gateway . . . . . . :
C:\>

Using the Registry

The Registry is a treasure chest of information for Windows workstations and servers. It contains lots of information regarding installed software and hardware, including specific configuration information. You can use the C# Registry classes to walk through the Registry on the system to determine many features, including the current IP network configuration. This section describes where to find IP information in the Registry, and how to extract it with a C# program.

IP Info in the Registry

The Registry consists of individual keys that store one or more data items. Each key stores information for an entity on the system, such as a network card. Each data item has a value that defines the data information. The Registry key organization is similar to a directory/ subdirectory structure. A key may contain data as well as several subkeys. Each subkey itself may contain data and additional subkeys; the structure can go several levels deep.

The Windows Registry comprises six base keys from which all other keys are built:

CLASSES ROOT

CURRENT CONFIG

CURRENT USER

DYN DATA

LOCAL MACHINE

USERS

The Registry base keys are prefixed with the term HKEY, thus the LOCAL MACHINE base key is accessed using the key HKEY LOCAL MACHINE. For shorthand purposes, this is often called HKLM.

Subkeys are referenced using a directory-like convention, using a backslash (\) to separate levels of subkeys:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion
Warning 

Note that the Registry contains key names that can be all uppercase, a mixture of upper- and lowercase, and words with spaces in them. This inconsistency often leads to problems when programming for the Registry.

The Registry contains network information for each installed network device on the system. Unfortunately, the various Windows platforms have their own storage locations for this information. Some platforms relate network information to the individual network interface cards (NICs), while others keep all network information in a common location. The following sections shows you how to find it for each platform.

Windows 98 and Me

Windows 98 and Me devices store network information in a single location, no matter how many network cards are configured on the system. You can always look in the same subkey to find all the IP configurations for the system:

HKLM\SYSTEM\CurrentControlSet\Services\Class\NetTrans

Within this subkey, the information for each network interface is stored as a separate subkey, named sequentially starting with 0000. Each subkey contains data values that define the IP information for an individual network device. Figure lists the IP data values contained in the subkey for a network interface.

Figure: Network Information Registry Data Names

Data Name

Description

IPAddress

The IP address assigned to this interface

DefaultGateway

The IP router assigned to this interface

IPMask

The subnet mask used to define the network address used on this interface

Windows NT, 2000, and XP

If you are looking for network information on a Windows NT, 2000, or XP system, you must first know what network cards are configured on the system. Network information on these platforms is stored within the individual network card Registry keys and not in a single location as it is for Windows 98 and Me. To obtain the IP address information, you must search for each network card and extract the network information from each location.

The first step is to find the Registry keys of all the network devices configured on the system. Windows NT, 2000, and XP systems have a single Registry key that lists all network interfaces configured on the system. This key is listed under the HKEY_LOCAL_MACHINE (HKLM) root key. The actual subkey is as follows:

HKLM\Software\Micrososft\Windows NT\CurrentVersion\NetworkCards

It has subkeys for each network interface on the system. Each subkey is numbered sequentially and will contain information about a single network interface installed on the system, stored as a data value to the subkey. The pertinent data value that you need to extract is the ServiceName data value. This value points to the network device entry in the Services Registry key where the IP information is stored.

Once the ServiceName value is obtained for each network device, the next step is to look at the Services information area for each network interface ServiceName. The appropriate ServiceName key will appear as a subkey under the base system services key:

HKLM\SYSTEM\CurrentControlSet\Services

Each system service has a subkey under this key that contains information for the particular service. The network interface ServiceName retrieved from the first step is used as the subkey name, so finding the proper information once you have a listing of all the ServiceNames is easy.

The IP information is stored as data values under the parameters\tcpip subkey of the Service key. The data names used for IP information in the subkey are similar to those shown for the Windows 98 and Me systems:

IPAddress

SubnetMask

DefaultGateway

It is a simple matter to get the IP information stored in the data values. The only tricky part is that on Windows NT, 2000, and XP, each individual network device may have more than one set of IP information. This means that the Registry IP data values for each device can contain more than one value. You must ensure that you retrieve all possible values for the IP data values

Note 

This method only works for network cards with static IP addresses. If your network is using DHCP to assign IP addresses, you will have to check the DhcpIPAddress Registry key values for your Windows platform instead.

Using C# to Search the Registry

Once you have determined where to find the network information in the Registry of your target system, you can create C# code to search for it and display the information to the user (or use it in your program). In this section, we’ll examine a C# program to query the system Registry for IP information.

The .NET Framework provides a set of classes that help you query and manipulate Registry entries. The .NET Registry classes are contained in two separate namespaces:

Microsoft.Win32.Registry The Microsoft.Win32.Registry namespace contains all the base classes needed to access the base Registry key names: Current_User, Local_Machine, Classes_Root, Current_Config, Dyn_Data, and Users. You must use one of the base Registry key names to build your specific Registry subkey.

Microsoft.Win32.RegistryKey The Microsoft.Win32.RegistryKey namespace contains the classes and methods necessary to query and modify Registry keys and data. The OpenSubKey() method allows you to open a subkey of a known key and access any data values contained in the subkey. Once you have the appropriate subkey, you can use the GetValue() method to get the data values assigned to the subkey.

Listing 2.2 presents the CardGrab.cs program, which will find the network devices installed on a Windows NT, 2000, or XP system using the system Registry, and display the IP information for each device.

Listing 2.2: CardGrab.cs program
Start example
using System;
using Microsoft.Win32;
class CardGrab
{
  public static void Main ()
  {
  RegistryKey start = Registry.LocalMachine;
  RegistryKey cardServiceName, networkKey;
  string networkcardKey = "SOFTWARE\\Microsoft\\ Â
      Windows NT\\CurrentVersion\\NetworkCards";
  string serviceKey =
      "SYSTEM\\CurrentControlSet\\Services\\";
  string networkcardKeyName, deviceName;
  string deviceServiceName, serviceName;
  RegistryKey serviceNames =
            start.OpenSubKey(networkcardKey);
  if (serviceNames == null)
  {
    Console.WriteLine("Bad registry key");
    return;
  }
  string[] networkCards = serviceNames.GetSubKeyNames();
  serviceNames.Close();
  foreach(string keyName in networkCards)
  {
    networkcardKeyName = networkcardKey + "\\" + keyName;
    cardServiceName = start.OpenSubKey(networkcardKeyName);
    if (cardServiceName == null)
    {
     Console.WriteLine("Bad registry key: {0}",
         networkcardKeyName);
     return;
    }
    deviceServiceName =
       (string)cardServiceName.GetValue("ServiceName");
          deviceName =
           (string)cardServiceName.GetValue("Description");
    Console.WriteLine("\nNetwork card: {0}", deviceName);
     
    serviceName = serviceKey + deviceServiceName +
      "\\Parameters\\Tcpip";
    networkKey = start.OpenSubKey(serviceName);
    if (networkKey == null)
    {
     Console.WriteLine("  No IP configuration set");
    } else
    {
      string[] ipaddresses =
        (string[])networkKey.GetValue("IPAddress");
      string[] defaultGateways =
        (string[])networkKey.GetValue("DefaultGateway");
      string[] subnetmasks =
        (string[])networkKey.GetValue("SubnetMask");
      foreach(string ipaddress in ipaddresses)
      {
        Console.WriteLine("  IP Address: {0}",ipaddress);
      }
      foreach(string subnetmask in subnetmasks)
      {
        Console.WriteLine("  Subnet Mask: {0}",
         subnetmask);
      }
      foreach(string defaultGateway in defaultGateways)
      {
        Console.WriteLine("  Gateway: {0}",
              defaultGateway);
      }
      networkKey.Close();
    }
  }
  start.Close();
  }
}
End example

You must define a root key to begin the key search. This is done using the Registry class:

RegistryKey start = Registry.LocalMachine;

This creates a Registry key object start and sets it to the root class HKLM_LOCAL_MACHINE.

Next, you drill down and set a key object to the pertinent subkey where the network device information is located:

string networkcardKey = "SOFTWARE\\Microsoft\\ Â
      Windows NT\\CurrentVersion\\NetworkCards";
RegistryKey serviceNames =
            start.OpenSubKey(networkcardKey);

Now the key object serviceNames points to the location of the installed network device subkeys.

Next you use the GetSubKeyNames() method to iterate through each of the network device subkey names. Because the same key name is used for the service keys, you can add that value to the known service key location and open the subkey using the OpenSubKey() method, again referenced from the root key:

  serviceName = serviceKey + deviceServiceName + "\\Parameters\\Tcpip";
  networkKey = start.OpenSubKey(serviceName);

Once each subkey is opened, the IP information is retrieved from the service key using the GetValue() method of the key object. Because each IP information data entry can have multiple values, you must assign the result to a string array and display the complete array using the foreach function:

string[] ipaddresses =
        (string[])networkKey.GetValue("IPAddress");
foreach(string ipaddress in ipaddresses)
{
  Console.WriteLine("  IP Address: {0}",ipaddress);
}

A sample output of the CardGrab program should look like this:

C:\>CardGrab
Network card: D-Link DE660 PCMCIA LAN adapter
  IP Address: 192.168.1.6
  Subnet Mask: 255.255.255.0
  Gateway: 192.168.1.1
C:\>

You can use a similar technique to find the IP information for Windows 98 or Me devices. In fact, that technique is much simpler because you only have to search in one location for the IP information.

Using WMI

In addition to the Registry, there’s another source available to you for obtaining IP network information from Windows systems. The Windows Management Instrumentation (WMI) is the Microsoft implementation of Web-Based Enterprise Management (WBEM), which is a standard for accessing system information in a network environment, developed by the Distributed Management Task Force, Inc. (DMTF). Since Windows 2000, Microsoft has included in the OS a database that contains information regarding system hardware and software, as well as current hardware status. The C# language can query the database to determine the status of managed hardware and software components, including network devices.

Tip 

Older Windows systems can have the WMI system installed as a separate download from the WMI Sofware Developers Kit. This download is freely available on the Microsoft software download website (http://www.microsoft.com/downloads/search.asp?).The WMI consists of multiple database tables that store system information, and they are updated as the status of each monitored device changes. These tables each track information for particular system functions. The C# WMI classes allow you to query the database and extract up-to-date information related to the running system.

IP Info in WMI

The WMI Win32 NetworkAdapterConfiguration table within WMI contains information related to the network devices installed on the system. The result of the table query is a collection of information for each network interface. Each network interface represents one record in the returned collection. The IP information for the network interface appears as separate fields within the record.

A wide variety of network data values are contained in the WMI database. Figure describes some useful IP data fields contained in the Win32 NetworkAdapterConfiguration table.

Figure: The Win32 NetworkAdapterConfiguration Data Fields

Field

Description

DefaultIPGateway

An array of IP router addresses assigned to the device

Description

The description of the network device

DHCPEnabled

Whether the device dynamically assigns its IP address

DHCPServer

The DHCP server used to assign an IP address

DNSHostName

The DNS host that is used for resolving hostnames

IPAddress

An array of IP addresses assigned to the device

IPEnabled

Whether the device uses IP on the network

IPSubnet

An array of IP subnet addresses used on the device

MACAddress

The Ethernet MAC address assigned to the network device

Applications can access the WMI database using standard SQL syntax queries. The queries must specify a table to query, along with the fields to return (or the * wildcard character to return all the fields). A sample SQL query would look like this:

SELECT IPAddress, IPSubnet from Win32_NetworkAdapterConfiguration

This SQL statement returns the IP address and subnet mask for each network interface configured on the system. Again, remember that any one interface can have multiple IP addresses, so this information is returned in the form of a multivalue array.

Now that you know where the WMI network information is stored, let’s look at an example of using C# to extract the information.

Using C# to Query WMI

The .NET System.Management namespace contains classes used for querying the WMI databases. You can create a C# program to query WMI for each network interface installed on the system and then display the IP information returned. The steps to use to query the WMI database from a C# program are as follows:

  1. Create a ManagementObjectSearcher object that contains a SQL Select statement for the database table.

  2. Create a ManagementObjectCollection object to obtain the result set from executing the SQL query.

  3. In a foreach loop, assign a new ManagementObject for each object in the Management-ObjectCollection.

  4. Assign the desired data fields to regular type variables.

Listing 2.3 shows the WMICardGrab.cs program, which uses the C# WMI classes to obtain the network interface IP information.

Listing 2.3: WMICardGrab.cs program
Start example
using System;
using System.Management;
class WMICardGrab
{
  public static void Main ()
  {
    ManagementObjectSearcher query = new
    ManagementObjectSearcher("SELECT * FROM Â
     Win32_NetworkAdapterConfiguration WHERE IPEnabled = 'TRUE'");
    ManagementObjectCollection queryCollection = query.Get();
    foreach( ManagementObject mo in queryCollection )
    {
      string[] addresses = (string[])mo["IPAddress"];
      string[] subnets = (string[])mo["IPSubnet"];
      string[] defaultgateways =
           (string[])mo["DefaultIPGateway"];
      Console.WriteLine("Network Card: {0}",
             mo["Description"]);
      Console.WriteLine("  MAC Address: {0}",
             mo["MACAddress"]);
      foreach(string ipaddress in addresses)
      {
        Console.WriteLine("  IP Address: {0}",
             ipaddress);
      }
      foreach(string subnet in subnets)
      {
        Console.WriteLine("  Subnet Mask: {0}", subnet);
      }
      foreach(string defaultgateway in defaultgateways)
      {
        Console.WriteLine("  Gateway: {0}",
             defaultgateway);
      }
    }
  }
}
End example

The C# WMI class ManagementObjectSearcher defines the SQL query that will be performed against the WMI database. You can use the IPEnabled field to your advantage, filtering out any network devices that do not have IP configured:

ManagementObjectSearcher query = new
    ManagementObjectSearcher("SELECT * FROM Â
    Win32_NetworkAdapterConfiguration WHERE IPEnabled = 'TRUE'");
ManagementObjectCollection queryCollection = query.Get();

The result of the query is stored in a ManagementObjectCollection. Each collection item represents one record in the result set, and each record represents one network interface. The handy foreach C# function can be used to iterate through the retrieved recordset collection, examining each record individually and assigning it to a ManagementObject object. Fields within the record are referenced using their proper field name:

string[] addresses = (string[])mo["IPAddress"];
string[] subnets = (string[])mo["IPSubnet"];
string[] defaultgateways = (string[])mo["DefaultIPGateway"];

Similar to the Registry version, the IPAddress, IPSubnet, and DefaultIPGateway values are arrays that can contain more than one value. To accommodate this, you must assign the result to a string array, and step through the string array, again with a foreach statement.

The IP information retrieved from the WMICardGrab program should be the same as from the Registry version:

C:\>WMICardGrab
Network Card: D-Link DE660 PCMCIA LAN adapter
  MAC Address: 00:80:C8:BC:CE:C3
  IP Address: 192.168.1.6
  Subnet Mask: 255.255.255.0
  Gateway: 192.168.1.1
C:\>

Using DNS

The last way to determine system IP information is to utilize the C# DNS (Domain Name System) classes. Chapter 4, “DNS and C#” contains a substantial discussion of how to use the DNS to obtain Internet hostnames and IP addresses. You can exploit this system to obtain the local IP address(es) of the system your program is running on.

The C# System.Net namespace contains the Dns class, which comprises several methods that allow you to obtain DNS information about hosts. The GetHostName() method retrieves the hostname of the local system. The GetHostByName() method attempts to find the IP address of a hostname. You can combine these two functions to find the IP address of the local system. Listing 2.4 shows the DNSName.cs program, which demonstrates using these functions to find the local IP address(es) of the system.

Listing 2.4: DNSName.cs program
Start example
using System;
using System.Net;
class DNSName
{
  public static void Main ()
  {
   string hostName = Dns.GetHostName();
   Console.WriteLine("Local hostname: {0}", hostName);
   IPHostEntry myself = Dns.GetHostByName(hostName);
   foreach (IPAddress address in myself.AddressList)
   {
   Console.WriteLine("IP Address: {0}", address.ToString());
   }
  }
}

Again, similar to the Registry and WMI programs, you must take into account the possibility of the local system having more than one IP address assigned to it. The AddressList property of the IPHostEntry class is an array of type IPAddress. You can use the foreach function to extract each of the IP addresses in the array. The output of this program is very simple:

C:\>DNSName
Local hostname: abednego
IP Address: 192.168.1.6
C:\>

This is a very common method to use to get the local system IP address for determining the local IP address to use for creating server network connections. You will see this code used many times in later chapters.

End example

 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows