Introduction
In a previous .NET project at work, I was asked to write a background process
that can wake up at specified time intervals, call certain stored procedures
to process a list of items retrieved from the database, and then send an
e-mail notification to the interested party for every item processed. I
immediately thought of doing it using a windows service. However, I
cannot use my
XYNTService here because no C++ code is allowed in this project. So it gives me
an excuse to write my first windows service in .NET.
I hate to write code that can only be used once, so I put some
effort into making this program simple and flexible enough that other people
might be able to use it later. The windows service executable is named
NotificationService.exe. Here is what the program does:
- Every 15 minutes the service will wake up and do the following processing.
- It calls a stored procedure to retrieve a list of items that needs to be processed.
- For each each item in the list, it calls another stored procedure to process the item.
- Then it sends an e-mail to notify the interested party.
- It will pause 1 second after processing each item to avoid hogging the CPU.
The time intervals it sleeps/pauses within the processing loop, the names
of the stored procedures called, the database connection string, and the
e-mail address as well as other fields, are all defined in an XML configuration
file. If you want to reuse this program, you need only to:
- Write two stored procedures, one to retrieve the list of items and
the other to process each item.
- Modify the XML configuration file.
- Run the windows service.
Of course, you can modify the service itself to do more complicated or customer-specific
work.
The configuration file
The file Notification.xml contains all the information
needed by NotificationService.exe. It should be placed in the Xml sub folder
of the current folder (where the executable
resides). Here is a sample of the Notification.xml
file.
<notificationservice>
<sleep>15</sleep>
<pause>1000</pause>
<dbconnection>Provider=myProvider;Database=myDatabase;Server=myServer;User
ID=myID;Password=</dbconnection>
<getlistproc>GetList</getlistproc>
<idfield>ID</idfield>
<processitemproc>ProcessItem</processitemproc>
<parametername>@ID</parametername>
<email>
<from>Sender@computer.domain.com</from>
<to>Receiver@computer.domain.com</to>
<cc></cc>
<bcc></bcc>
<subject>Notification Service</subject>
<body>This is a notification</body>
</email>
</notificationservice>
The <sleep> element is
the number of minutes the program will sleep before waking up to retrieve
and process the list of items. The <pause> element is the number
of milliseconds the program will sleep after processing each item.
The <dbconnection> element
is the database connection string. The <getlistproc> element contains the name of the stored
procedure that retrieves the list of items from the database, the procedure
returns a list of item identifiers (can be either strings or numbers). The <idfield>
element is the field name of the previous stored procedure. The element <processitemproc>
contains the name of the stored procedure to process each item, the procedure
takes a parameter (the item identifier) whose name is in the <parametername>
element.
The <email> element contains various fields used in the notification e-mail.
If the <to> element is missing or empty, then no e-mail notification will be sent.
How the service works and how to install
When start up, the service will load the XML configuration file. Then
it will spawn a worker thread that does the real processing job. When
you stop the service, the worker thread will be killed.
The Working
method is called
by the worker thread to retrieve and process items. The
XMLDB.dll
described in my other CodeProject article is used to do all database work.
Once you have the correct connection string defined in the
XML configuration file, you will never have to worry about the database connection.
Even if the database server is shutdown and later restarted, there
is nothing that has to be done to the service because the component knows
how to reconnect to the database automatically.
To install the program, you first unzip the 3 files NotificationService.exe,
XMLDB.dll, and ServiceInstaller.exe into a folder on a machine
that already has the .NET framework and copy the Notification.xml
file to a sub folder named Xml. The following commands will install
and start (run) the service (you need to change the file path to match the
folder on your machine):
ServiceInstaller -i NotificationService c:\[...]\NotificationService.exe
ServiceInstaller -r NotificationService
The following commands will stop (kill) the service and un-install it:
ServiceInstaller -k NotificationService
ServiceInstaller -u NotificationService
The utility
ServiceInstaller.exe
is described in one of my other articles.
The implementation
The implementation is very simple. The class NotificationService
is derived from
System.ServiceProcess.ServiceBase
. The OnStart
and
OnStop
methods are overridden to create and destroy the worker
thread. The Working
method is called by the worker thread periodically to
retrieve and process items from the database.
The code is straightforward but it does demonstrate some basic programming techniques in the
.NET environment. I hope at least one of
you find this program useful. Check out my
home page for other programs and articles.