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)’.
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.
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.