.NET Network Monitor
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.
When cable had bad contact, it's also get information.
Connect succeed.
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.
发表评论
6HysZ6 Im no expert, but I consider you just made an excellent point. You naturally understand what youre talking about, and I can truly get behind that. Thanks for staying so upfront and so truthful.
hchpfB Some truly choice posts on this website , saved to favorites.