Introduction

I need to monitor Network status in my project.To check the cable has bad contact or not and to check network is enable or not.So I develop a simple tool to test.

Background

This sample is using WMI to get information in .NET.

Using the Code  

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

NetworkManager.Instance.StartMonitor();

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

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 destory: 

NetworkManager.Instance.Destory();

About the Code

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, this enum named NetConnectionStatus that is reference from the property NetConnectionStatus in Win32NetworkAdapter class. 

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

static readonly NetworkManager m_instance = new NetworkManager(); 

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

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);
    }
}

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 Windows Console, so I use the property to be a key.

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

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

Executing image

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

11.JPG

 When cable had bad contact, it's also get information.  

13.JPG

 Connect succeed.  

12.JPG

Points of Interest  

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

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,
    }
}
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 InternetGetConnectedState API, I found the API already return ture when I disable a network card.(I have two network cards.)

In my project the FrontEnd will get client's data with LAN but the FrondEnd also need to connect to WAN with another network card.

So I think this function can not help me to handle all network status.

If you want to use API in .NET, you must use DllImport to declare API. 

The enum ConnectionStates is flag value, convert flags to ConnectionStates and use ToString() can get understand information. 

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

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 two network cards in my PC.

When I use these code to get network information and network is connected, it will display understand information.

The OperationalStatus property will show Up. 

And it will get Down when I remove cable from network card.

But I think the perfect solution not only handle the network cable, so I try to disable network in Windows Console.

After disable a network, I run these code again, but here doesn't show the disable network card's information.

So I think NetworkInterface maybe not a perfect solution.

History  

V1.2 Update source code project.

V1.1 Add more detail.  

V1.0 Add for Network Monitor. 

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架