Search Wiki:

Re-Building Network Utilities


Hilary Pike
Academic Developer Evangelist
Microsoft Corporation

Introduction

This is a simple network utility that will look for devices on the network. It’s a re-build and re-design of this Coding4Fun article http://blogs.msdn.com/coding4fun/archive/2006/10/31/914076.aspx. I examined the approach described in this article; however, I couldn’t quite follow the choices made by the author. I implemented the tool using a ThreadPool and provided an interface that offers both my implementation ‘Scan (Thread Pool)’ and the previous implementation ‘Scan (Threads)’.

screenshot1.png

The project explores the System.Net.NetworkInformation namespace, the ListView Control, generics for the callbacks, System.Threading.ThreadPool, and finally form resizing all using Visual Studio 2008 Express Edition http://www.microsoft.com/express/.

System.Net.NetworkInformation

The core functionality of this utility is to ping network addresses to determine what devices might be alive on the network. This becomes almost a trivial task using System.Net.NetworkInformation.Ping. This class sends an ICMP echo request to a specified address.
C#
//multi-line
            Ping ping = new Ping();
            PingReply pr = ping.Send(ip);
One interesting thing I discovered using the PingReply Class (System.Net.NetworkInformation.PingReply) in the steps above, is that the PingReply.Address will be set to the address of the reply sender. For example, if you send a ping to 123.456.789.000 and that address corresponds to 60.50.40.30, PingReply.Address will be set to 60.50.40.30. In this implementation, I chose not to disclose those translations to the user interface although it might be valuable to add an additional column to show that information to the user. To hide this result, I added IPAddress to the class NetScanCompletedEventArgs
    public class NetScanCompletedEventArgs : EventArgs
    {
        public PingReply pReply;
        public IPAddress ip;  
    }

User Interface

One of the tricky aspects of this program was to coordinate the threads and the updates to the user interface. It’s important not to have multiple threads updating the User Interface (UI) at the same time. I created a single method that updates a form control to avoid updating the controls from multiple spots in the code (ButtonUpdate and ListViewUpdate). Finally, in the two event handlers (NetScanCompleteHandler and PingCompleteHandler) the use InvokeRequired tests to see if the updates to the form are happening on the main application thread and uses Invoke to update the form from a worker thread.
I haven’t created many Windows Form applications before and ran into a few UI issues that may seem trivial to some. Given this is a multi-threaded application, the updates to the user interface may not come in any specific numeric order. When I first set-up my ListView the IPAddress column was not sorted and hard to read. The ListView has a ListView.Sorted property that can be set in the Properties window to sort the items posted to the ListView.

screenshot2.png

The second issue was that the ListView did not resize appropriately with the Form. When many results were returned, I wanted to stretch the form to see more IP Addresses. To make this change, I had to capture the Form.ResizeEnd event. This event is fired when the user is finished resizing the form. I had some mis-steps at first trying to capture Form.Resize which is called at each movement of the form. A new feature in Visual Studio 2008 is that you can set that the Properties Window allows you to toggle between events and properties. I solved this problem by creating the Form1ResizeEnd_ method and resetting the ListView size to always be 180 less than the entire form size.

screenshot3.png
Last edited Jun 16 at 3:58 PM  by HilaryP, version 9
Comments
Paw_J wrote  Jul 31 at 7:23 AM  
needless to say that some of your code could be optimized, like this:

public void ButtonUpdate(bool b)
{
if (b)
{
btnScanThreadPool.Enabled = true;
btnScanThreads.Enabled = true;
}
else
{
btnScanThreadPool.Enabled = false;
btnScanThreads.Enabled = false;
}
}

optimized version:
public void ButtonUpdate(bool b)
{
btnScanThreadPool.Enabled = b;
btnScanThreads.Enabled = b;
}

;o)

anyway, nice work on the threadpool execution ;o)

pop_k wrote  Aug 1 at 6:41 AM  
I just notice that when you
click Scan (Thread Pool) button will ns.start
and click Scan (Threads) button will pns.start.

But NetScan ns;
PoolNetScan pns;

What 's wrong with the code??????

please check again.

Updating...
Page view tracker