Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

.NET Network Monitor

4.73/5 (20 votes)
22 Jul 2011CPOL3 min read 123K   12.9K  
A simple network monitor.

Introduction

In this article, I will present my custom class NetworkManager and explain my design idea. And I will present other references, that is using the Win32 API InternetGetConnectedState and the .NET Framework NetworkInterface, but at last, I will not use InternetGetConnectedState and NetworkInterface.

In here, you will learn these techniques.

Background

I need to monitor the network status in my project. This is to check if the cable has a bad contact or not and to check if the network is enabled or not. So I developed a simple tool to test.

Why do I need to monitor the network status? Because in our product, we had an issue where the cable had a bad contact with the network vard. So the user requested for a solution and we talked about this issue in our team meeting. We thought we needed a complete solution, and maybe the user will also disable the network in the environment.

Using the Code

I use a singleton to manage all the network information. Now, call this code to initialize and monitor:

C#
NetworkManager.Instance.StartMonitor();

And foreach NetworkManager.Instance.Informations.Values to get the required information:

C#
foreach(NetworkInfo info in NetworkManager.Instance.Informations.Values)
{
    Console.WriteLine("Device Name:" + info.DeviceName);
    Console.WriteLine("Adapter Type:" + info.AdapterType);
    Console.WriteLine("MAC Address:" + info.MacAddress);
    Console.WriteLine("Connection Name:" + info.ConnectionID);
    Console.WriteLine("IP Address:" + info.IP);
    Console.WriteLine("Connection Status:" + info.Status.ToString());
}

At last call this to destroy:

C#
NetworkManager.Instance.Destory();

About the Code

C#
public enum NetConnectionStatus
{
    Disconnected = 0,
    Connecting = 1,
    Connected = 2,
    Disconnecting = 3,
    HardwareNotPresent = 4,
    HardwareDisabled = 5,
    HardwareMalfunction = 6,
    MediaDisconnected = 7,
    Authenticating = 8,
    AuthenticationSucceeded = 9,
    AuthenticationFailed = 10,
    InvalidAddress = 11,
    CredentialsRequired = 12
}

First, the enum named NetConnectionStatus that is a reference from the property NetConnectionStatus in the Win32NetworkAdapter class.

In my project, I need the information, so I declared it.

C#
static readonly NetworkManager m_instance = new NetworkManager();

I use singleton for NetworkManager, because I think this class will get the information as network cards, and all instances will get the same information, so singleton is the best.

C#
static NetworkManager()
{
    ManagementObjectSearcher searcher = new ManagementObjectSearcher(
        "SELECT * FROM Win32_NetworkAdapter WHERE NetConnectionID IS NOT NULL");
    foreach (ManagementObject mo in searcher.Get())
    {
        NetworkInfo info = new NetworkInfo();
        info.DeviceName = ParseProperty(mo["Description"]);
        info.AdapterType = ParseProperty(mo["AdapterType"]);
        info.MacAddress = ParseProperty(mo["MACAddress"]);
        info.ConnectionID = ParseProperty(mo["NetConnectionID"]);
        info.Status = (NetConnectionStatus)Convert.ToInt32(mo["NetConnectionStatus"]);
        SetIP(info);
        m_Informations.Add(info.ConnectionID, info);
    }
}
C#
static void SetIP(NetworkInfo info)
{
    ManagementClass objMC = 
       new ManagementClass("Win32_NetworkAdapterConfiguration");
    foreach (ManagementObject mo in objMC.GetInstances())
    {
        try
        {
            if (!(bool)mo["ipEnabled"])
                continue;
            if (mo["MACAddress"].ToString().Equals(info.MacAddress))
            {
                string[] ip = (string[])mo["IPAddress"];
                info.IP = ip[0];
                string[] mask = (string[])mo["IPSubnet"];
                info.Mask = mask[0];
                string[] gateway = (string[])mo["DefaultIPGateway"];
                info.DefaultGateway = gateway[0];
                break;
            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine("[SetIP]:" + ex.Message);
        }
    }
}

The ConnectionID will show in the Windows Console, so I use the property to be a key.

I use ManagementObjectSearcher to get the network card information in Win32_NetworkAdapter, but IP, subnet, and gateway is available in Win32_NetworkAdapterConfiguration.

WQL can't use the join table, so I use the SetIP function that will get the IP address in Win32_NetworkAdapterConfiguration by MACAddress, because MACAddress exists in Win32_NetworkAdapter and Win32_NetworkAdapterConfiguration.

Executing Image

When we disable the network in the Console, the Monitor will get the disconnect status.

11.JPG

When the cable has a bad contact, it gets that information.

13.JPG

This is when the Connect succeeds:

12.JPG

Points of Interest

Apart from WMI, I also try InternetGetConnectedState API and NetworkInterface.

C#
public class WinINET
{
    [DllImport("wininet.dll", SetLastError = true)]
    public extern static bool InternetGetConnectedState(out int lpdwFlags,
        int dwReserved);

    [Flags]
    public enum ConnectionStates
    {
        Modem = 0x1,
        LAN = 0x2,
        Proxy = 0x4,
        RasInstalled = 0x10,
        Offline = 0x20,
        Configured = 0x40,
    }
}
C#
static void WinINETAPI()
{
    int flags;
    bool isConnected = WinINET.InternetGetConnectedState(out flags, 0);
    Console.WriteLine(string.Format("Is connected :{0} Flags:{1}", isConnected,
        ((WinINET.ConnectionStates)flags).ToString()));
}

When I try the InternetGetConnectedState API, I find the API already returns true when I disable a network card. (I have two network cards.)

In my project, the front-end will get the client's data with LAN but the front end also needs to connect to the WAN with another network card. So I think this function will not help me handle all the network status. If you want to use an API in .NET, you must use DllImport to declare the API.

The enum ConnectionStates is a flag value, converts flags to ConnectionStates, and using ToString(), we can get the required information.

For example, when flags = 0x18, convert to ConnectionStates and using ToString() will get the "LAN,RasInstalled" string.

C#
static void NetInfo()
{
    foreach (NetworkInterface face in 
             NetworkInterface.GetAllNetworkInterfaces())
    {
        Console.WriteLine("=================================================");
        Console.WriteLine(face.Id);
        Console.WriteLine(face.Name);
        Console.WriteLine(face.NetworkInterfaceType.ToString());
        Console.WriteLine(face.OperationalStatus.ToString());
        Console.WriteLine(face.Speed);
    }
}

Here are the two network cards in my PC.

When I use this code to get network information and the network is connected, it will display the information. The OperationalStatus property will show up. And it will get Down when I remove the cable from the network card.

But I think the perfect solution not just handles the network cable, so I tried to disable the network in the Windows Console. After disabling the network, I run the code again, but it doesn't show the disabled network card's information.

So I think NetworkInterface may not be a perfect solution.

History

  • V1.3: Updated information and background.
  • V1.2: Updated source code project.
  • V1.1: Added more detail.
  • V1.0: Added code for Network Monitor.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)