|
Write a comment |
Articles |
DHTML Gallery |
.NET |
MyBlog |
About Me |
FAQ
|
|
|
Quick and dirty network usage meter with C#
Download source code. I have always been doubtful of my billing by my internet providers. I wanted to write some code that could help me get a rough estimate of bandwidth I was using in every session. In this article, I will show you how to create a very basic network usage meter for serial port/USB/mobile phone modems with only C# (no Win API calls, sockets or fancy stuff).
The basics
The Code
static PerformanceCounter dataSentCounter;
static PerformanceCounter dataReceivedCounter;
System.Timers.Timer networkMonitor;
string category, instance, fileName;
static float u, d;
public Form1()
{
InitializeComponent();
category = ConfigurationSettings.AppSettings["Category"];
instance = ConfigurationSettings.AppSettings["Instance"];
fileName = ConfigurationSettings.AppSettings["FilePath"];
dataSentCounter = new PerformanceCounter(category, "Bytes Transmitted", instance);
dataReceivedCounter = new PerformanceCounter(category, "Bytes Received", instance);
NetworkChange.NetworkAvailabilityChanged += new NetworkAvailabilityChangedEventHandler(NetworkChange_NetworkAvailabilityChanged);
networkMonitor = new System.Timers.Timer();
networkMonitor.Interval = Int32.Parse(ConfigurationSettings.AppSettings["NetworkPollInterval"]);
networkMonitor.Elapsed += new ElapsedEventHandler(networkMonitor_Elapsed);
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
u = dataSentCounter.NextValue();
d = dataReceivedCounter.NextValue();
}
catch
{ return; }
networkMonitor.Start();
}
In the above code, 'category' is set to "RAS Port" and 'instance' to "COM4". The instance needs to be set to correct port number to which your modem is connected to. To get instance name of your COM port you can do something like this:
PerformanceCounterCategory c = new PerformanceCounterCategory("RAS Port");
//c.GetInstanceNames() gives list of all instance names.
//Typically there will not be many COM ports. Use guess work
// and some experimenting to get the correct name. Make sure that you
// are connected to internet using a COM port before executing this.
Another important value is "Interval" of the timer. It should be sufficiently high (ideally 1-3 seconds). If you keep it too low the code might now work, because it seems the 'NetworkAvailabilityChanged' event takes some time to fire once you are physcially disconnected from the network. (Another reason for calling this code 'dirty'). Two important pieces are the 'NetworkAvailabilityChanged' event handler and code for 'Elapsed' event of the timer. When the timer's 'Elapsed' event fires, I try to read from the performance counters. If there is an exception reading, or 0 bytes recorded in the read operation, we first log the prior readings to a file. This indicates that the COM4 port was removed or network connectivity was lost. Notice here that, I am NOT relying on 'NetworkAvailabilityChanged' change event to inform me of a connection drop. (Why ..I told you, this is a 'dirty' approach).Instead we only use the 'NetworkAvailabilityChanged' event to check if a new network is available. When network is available we simply start the timer again.
void networkMonitor_Elapsed(object sender, ElapsedEventArgs e)
{
float temp_u=0, temp_d=0;
try
{ temp_u = dataSentCounter.NextValue();
temp_d = dataReceivedCounter.NextValue();
}
catch
{
LogUsage();
u = 0; d = 0;
networkMonitor.Stop();
return;
}
if (temp_u == 0f && temp_d == 0f)
{
LogUsage();
networkMonitor.Stop();
return;
}
u = temp_u; d = temp_d;
}
void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
{
if (e.IsAvailable)
{networkMonitor.Start();}
}
As you can see from the screen shot, I have added a notification icon to the Form. When user moves mouse pointer over this icon, it shows the usage. If the user right clicks, a popup menu comes up with "exit" item. On clicking this, our application closes. The code for this part is given below:
private void notifyIcon1_MouseMove(object sender, MouseEventArgs e)
{
notifyIcon1.Text = string.Format("{0}\nDn:{1} bytes, Ul:{2} bytes",instance,d,u);
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{ this.Close(); }
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
LogUsage();
dataSentCounter.Close();
dataReceivedCounter.Close();
}
The code for function that performs loggin of the usage in a CSV file.
private void WriteUsageToFile()
{
if (!File.Exists(fileName))
File.Create(fileName);
string username = System.Environment.UserName;
string logEntry = string.Format("{0},{1},{2},{3}\n", d, u, username, DateTime.Now.ToLongTimeString());
File.AppendAllText(fileName, logEntry);
}
private void LogUsage()
{
try
{
if(u > 0f || d > 0f)
WriteUsageToFile();
u = 0; d = 0;
}
catch (Exception ex)
{
MessageBox.Show(this, ex.ToString());
networkMonitor.Stop();
}
}
Finally! |
| Copyright (c) 2007-2009 Ashish Patil . Please read FAQ for more details. |