Introduction
This is yet another Ping Monitor utility written in VB.NET on .NET Framework 2.0. It fulfills the need of steadily monitoring through a "PING" the status (the aliveness) of some PCs and servers on a network, keeping a history of each state transition (ON to OFF and viceversa) and visually highlighting the last status of each machine.
This application is far from being a complete and sophisticated tool. I wrote it for a colleague who needed a starting point for a more advanced and customized tool implementation.
One service, one database, one IU
In order to continuously monitor some machine, we need to have a monitoring EXE continuously runnning. So, I decided to implement the "monitor engine" as a Windows Service application (taking advantage of unattended execution, automatic restart in case of power failure, and so on). This PingMonitorService
simply has to:
- read from some configuration storage (such as a database table) the list of machines to be monitored (along with the monitoring frequency);
- execute the actual monitoring sending a "PING" to each machine configured as to be monitored;
- log the outcome of each "PING" somewhere.
Other than a Windows Service for the monitoring and a database as a storage, we obviously need also a user interface (UI) to interact with the configuration and the log; that's why I created a simple Windows Form application (named PingMonitor
) to accomplish these tasks: showing the last PING status of the monitored machines and editing the PingMonitorService
configuration.
I decided to use a SQL Server 2000 (or 2005) database to host both the configuration (that is, a list of machines to be monitored) and the log.
The following are the two table schemas, expressed in T-SQL code, with some explanations.
The configuration table
CREATE TABLE HostList (
ID int IDENTITY(1,1) NOT NULL,
Host nvarchar(50) NULL,
IsHost char(1) NULL,
ShowInMonitor char(1) NULL,
DoPing char(1) NULL,
PingFreq int NULL,
IDparent int NULL,
CONSTRAINT PK_HostList PRIMARY KEY CLUSTERED (ID ASC)
WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON PRIMARY
) ON PRIMARY
The HostList
table will contain the list of the machines to be monitored. For each machine, it stores: the machine name with a unique ID (Host
and ID
fields), the frenquency of monitoring (PingFreq
field, expressed in seconds), a flag indicating if the monitoring is currently activated (DoPing
field) and a flag indicating if the specific machine has to be shown in the UI (ShowInMonitor
field).
Being able to list a hierarchycal tree enables you to organize the machines to be monitored in groups and subgroups, the HostList
table supports the concept of parent-child node relationships (via the IDparent
field) and the concept of "folder" tree nodes, that are intermediate nodes not corresponding to an host but simply being the parent of other nodes (for them, the IsHost
flag is not set to "yes").
The user interface provided by the PingMonitor
application allows you to visually edit the tree while directly modifying the underlying HostList
table (please, notice that the deletion of nodes and the addition of children nodes is allowed through the context menu on the tree).
The log table
CREATE TABLE PingLog (
Host varchar(50) NOT NULL,
Status varchar(5) NOT NULL,
RecordingDate datetime NOT NULL,
CONSTRAINT [PK_PingLog] PRIMARY KEY CLUSTERED (Host ASC, Status ASC,
RecordingDate ASC)
WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON PRIMARY
) ON PRIMARY
The PingLog
table will contain an entry for each detected state transition (ON to OFF or viceversa) for each monitored machine during a monitored period of time. The Host
field contains the name of the monitored machine, the RecordingDate
field contains a timestamp of the recorded entry and the Status
field simply contains the value "ON" or "OFF" (respectively indicating a successful and an unsuccessful "PING").
Some notes about the service
The PingMonitorService
has been implemented on the standard Windows Service application template of Visual Studio 2005. Being a standard .NET Windows Service, it has to be installed through the installutil.exe utility (see here for reference).
When started, the service reads its CONFIG file in order to retrieve:
- the connection string to the configuration database (see
ConnStr
appSetting) - the configuration reloading frequency (see
ReloadConfigFrequency
appSetting): it indicates the number of seconds before reloading all the configuration parameters (this enables the service to adapt its behavior based on new settings in the HostList
table eventually modified by the user through the PingMonitor UI).
To determine if it's time to "PING" a machine, the service simply looks at the total number of seconds passed after midnight and checks if this number is a multiple of the specific PingFreq
for that host (notice that only status transitions are stored, not each status detection).
If CurrentSecond Mod CInt(dr("PingFreq")) = 0 Then
Dim IsAlive As Boolean = HostIsAlive(dr("Host"))
Dim LastStatus As String = HostLastStatus(dr("Host"))
If LastStatus = "" OrElse _
(LastStatus = "ON" And Not IsAlive) OrElse _
(LastStatus = "OFF" And IsAlive) Then
StoreStatusTransition(dr("Host"), IsAlive)
End If
End If
Notice that the polling interval in the MainTask()
is currently set to 900ms, to be sure that at least one "tick" happens for every second (obviously, it could occur twice in some seconds). If the host list is very very big, the execution of the TryPing()
method could be long enough to make the service miss some "PING" to some hosts (so please carefully configure the hosts list and the specific PingFreq
s).
The "PING" itself is done, in a very simple way, through the System.Net.NetworkInformation.Ping
class:
Private Function HostIsAlive(ByVal Host As String) As Boolean
Dim pingSender As New Ping
Dim reply As PingReply
Try
reply = pingSender.Send(Host)
If reply.Status = IPStatus.Success Then
Return True
Else
Return False
End If
Catch ex As Exception
Return False
End Try
End Function
Some notes about the UI
The UI application is very simple; it consists of two forms: the monitoring form and the configuration form.
The application needs a CONFIG file where the connection string to the support database is specified (see ConnStr
appSetting).
The monitoring form is just a DataGridView
populated by a query on the PingLog
table; the query is designed to show only the last entry for each host having ShowInMonitor='Y'
.
The refresh frequency for the DataGridView
can be specified in the ReloadFrequency
appSetting of the application configuration file. Entries with an "OFF" status are highlighted by simply implementing the CellFormatting()
event handler:
Private Sub dgMonitor_CellFormatting(...)
Handles dgMonitor.CellFormatting
Dim v As Object = dgMonitor.Rows(e.RowIndex).Cells("Status").Value
If v IsNot Nothing AndAlso v.ToString() = "OFF" Then
For Each i As DataGridViewCell In dgMonitor.Rows(e.RowIndex).Cells
i.Style.BackColor = Color.Orange
Next
End If
End Sub
The configuration form contains a treeview with a detail panel, shown when a host node is selected (see the first picture in the article).
No special remarks needed on this. Just notice that the update of the underlying HostList
table is done immediately after modifying values on the UI controls, through updates on the corresponding DataTable
suddenly written down by the DataAdapter
.
Conclusions
As stated in the Introduction, this application is to be considered as a starting point for a more advanced and customized tool implementation. Its basic idea and implementation are intentionally very simple, hoping it can be useful for you in building something more complex.
Downloads
Content of the downloadable ZIP (now available also in a C# version) for this article:
- the
DBTablesCreation.sql
file - contains the T-SQL scripts for creating support database tables on Microsoft SQL Server 2000/2005; - the
PingMonitorService
folder - contains the Visual Studio 2005 project for the service; - the
PingMonitor
folder - contains the Visual Studio 2005 project for the UI WinForm application.