Network Monitor for Windows 7
If you are using Windows 7 you may have noticed that Microsoft decided to remove the Network Activity icon from the tray area and instead, substituted it with a dull plain white icon.
According to this video at Channel 9, the design team for Windows 7 removed it because they wanted to make Windows quieter. Well, I’m all for “quieter” as long as it doesn’t compromise an important feature.
Since I find it very important to know how much activity (if any) is going on through my network adapter I decided to code a small utility that would mimic the behavior of the old Network Icon.
The application is very simple: launch it and then right click its icon to select the network adapter that you want to monitor… and that’s it.
As a bonus, I added the ability to display a customizable led-type display of the network activity by double clicking the icon (click the image below to see it full size).
Note that the led bars can be moved and resized and all settings, including the selected Network Adapter are saved across sessions.
Simple but very useful.
Here you can download the binary version (which requires the Microsoft .NET Framework 4 Client Profile):
Network Monitor for Windows 7 (2715 downloads )
And here you can download its source code as a Visual Studio 2010 project:
Network Monitor Source Code for Windows 7 (2317 downloads )
How does Network Monitor work?
Network Monitor uses the Performance Counters provided through the Windows Management Instrumentation (WMI) API as exposed by the .NET through the System.Runtime.InteropServices namespace.
Although using WMI can facilitate the task of accessing the Performance Counters under Windows, there’s a major issue with localization. The counters are accessed by their name which varies under every language so an application that uses WMI needs to be able to determine the name of the counter as it is spelled under the language which the OS is running. Terrible… I know.
After doing some research (nice word for Googling) I was able to find that Windows keeps a list of the counter names in the Registry and each counter is given an ID so in order to make the Network Monitor program work under any language I coded a small routine that gathers the appropriate name for the counters based on their ID.
Here’s the code that does the magic:
Dim categoryName As String = "" Dim counterNameReceived As String = "" Dim counterNameSent As String = "" Dim counterNameBandwidth As String = "" Dim firstInstanceName As String = "" Dim countersNames() As String = CType(My.Computer.Registry.LocalMachine.OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\CurrentLanguage").GetValue("Counter"), String()) For i As Integer = 0 To countersNames.Length - 2 Step 2 If countersNames(i) = "510" Then categoryName = countersNames(i + 1) If countersNames(i) = "264" Then counterNameReceived = countersNames(i + 1) If countersNames(i) = "506" Then counterNameSent = countersNames(i + 1) If countersNames(i) = "520" Then counterNameBandwidth = countersNames(i + 1) Next
Once you know the names of the counters is a matter of instantiating them:
pcBytesRecv = New PerformanceCounter(categoryName, counterNameReceived, True) pcBytesSend = New PerformanceCounter(categoryName, counterNameSent, True)
Finally, Network Monitor starts a thread that keeps querying the values returned by the counters to determine when a send or receive operation is being performed:
Do Try curRecv = pcBytesRecv.NextValue() curSend = pcBytesSend.NextValue() If delay = 0 Then maxRecValue = Math.Max(maxRecValue, curRecv) maxSndValue = Math.Max(maxSndValue, curSend) Else delay -= 1 End If If lastRecv <> curRecv OrElse lastSend <> curSend Then Me.Invalidate() DrawTryIcon() lastRecv = curRecv lastSend = curSend End If Thread.Sleep(250) Catch End Try Loop Until cancelThreads
So every time a read or write state changes, the program updates the tray icon by calling the DrawTryIcon() sub, which looks like this:
Private Sub DrawTryIcon() Dim bmpIcon As Bitmap = Nothing If curRecv <> 0 OrElse curSend <> 0 Then bmpIcon = New Bitmap(16, 16) Dim b As SolidBrush Dim g As Graphics = Graphics.FromImage(bmpIcon) If curSend > minThreshold Then g.DrawImageUnscaled(My.Resources.ledon, 4, 0) b = New SolidBrush(Color.FromArgb(200, Color.Red)) g.FillRectangle(b, 6, 2, 8, 6) b.Dispose() Else g.DrawImageUnscaled(My.Resources.ledoff, 4, 0) End If If curRecv > minThreshold Then g.DrawImageUnscaled(My.Resources.ledon, 0, 6) b = New SolidBrush(Color.FromArgb(200, Color.LimeGreen)) g.FillRectangle(b, 2, 8, 8, 6) b.Dispose() Else g.DrawImageUnscaled(My.Resources.ledoff, 0, 6) End If g.Dispose() Else bmpIcon = My.Resources.neticon End If Dim oldIcon As Icon = niIcon.Icon Try niIcon.Icon = Drawing.Icon.FromHandle(bmpIcon.GetHicon) Catch bmpIcon = My.Resources.neticon End Try DestroyIcon(New HandleRef(Me, oldIcon.Handle)) oldIcon.Dispose() bmpIcon.Dispose() End Sub
Basically, the subroutine simply draws over the standard Windows Network Icon based on the status of the curSend and curRecv variables, so when their value is over a pre-defined threshold, a color is painted over the appropriate area in the icon to represent the send or receive states of the selected network adapter.
Finally, the led bars are painted right over the form using the following code:
If maxRecValue = 0 Then Return Dim g As Graphics = e.Graphics Dim rSend As Rectangle = Me.DisplayRectangle Dim rRecv As Rectangle = Me.DisplayRectangle rRecv.Height = rRecv.Height \ 2 + 2 rRecv.Inflate(-4, -4) DrawBar(g, CInt(rRecv.Width * (gRecv / maxRecValue)), rRecv, Brushes.DarkGreen, Brushes.LightGreen) rSend.Y += (rRecv.Height + 4) rSend.Inflate(-4, -4) rSend.Height = rRecv.Height DrawBar(g, CInt(rSend.Width * (gSend / maxSndValue)), rSend, Brushes.DarkRed, Brushes.Red) For x As Integer = rRecv.Left To rRecv.Right Step 2 g.DrawLine(Pens.Black, x, rRecv.Top, x, rSend.Bottom) Next PrintText(g, String.Format("{0:F1} KB/s", (gSend / 1024)), rSend) PrintText(g, String.Format("{0:F1} KB/s", (gRecv / 1024)), rRecv)
Notice that the code actually draws two solid bars and then a For…Next cycle is run to paint black lines at 1 pixels intervals to create the illusion that the bars are actually leds.
So, basically that is it. Feel free to grab the source code from the link above and play with it. As with all the source code distributed in this blog, you are free to use it for any purpose.
Recent Comments