Hi...
1.
This part of the tutorial is especially
focused on the Windows Service creation, configuration and installation. The
concepts (precisely the database and class library) used in this part is
already created and explained in the Part 1 of the tutorial.
2.
Apart from the continuation from Part
–1, this Part can actually be implemented separately according to the
requirement. At the same time, this part of the tutorial can be implemented
with variety of concepts like XML, EF, LINQ etc. So it is typically based on
the requirement to make different pieces fall in place.
In this part of the tutorial, we first create a Windows Service
Project, then implement a Service called – ‘BirthdayEmailService’. Then we add
a reference to our previously created Class Library – ‘EmailComponent’. We code
BirthdayEmailService using Timer to perform the email sending task for every
hour. Then we incorporate the Installer classes for the purpose of
installation. Finally a Setup and Deployment Project is created for the
Service. Finally the complete Solution is build and the exe file is generated
which is ready enough to get installed.
IMPORTANT – The logic in the using the Timer is to send emails
in particular intervals of time. The timer interval is set to 60mins, and it is
set to that value solely for demonstration purpose. According to the written
logic, emails will be send only for the first time elapsed event of a
particular date, so that the repetition of sending emails to the same customers
can be avoided. Always remember, logic in the service Time Event can be
modified according to ones requirement.
================================================================================================
BirthdayEmailService
Project
This section narrates how to
create a Windows Project. It also discuss how to prepare the project according
to our requirement (say adding references etc).
================================================================================================
Let’s get started with the creation of Windows Service.
1.
Open VS 2010
2.
File -> New -> Project
3.
Select ‘Visual C#’ -> Windows
-> Windows Service Template -> Give Name ‘BirthdayEmailSevice’
4.
Delete the default Service1.cs
To access Database i.e., CustomerDB, we include a app.config
file which in this case hold the data corresponding to the database
connectivity ( like connection string etc).
To add app.config file -
1.
Right click ‘BirthdayEmailService’ in
the solution explorer –> Select ‘Add New Item’.
2.
Select ‘Visual C#’ -> Select
Application Configuration File Template -> Click ADD.
To make the ConfigurationManager ( which is used to access
config file settings in the code), we add reference to System.Configuration.dll
to the project (right click Project ‘BirthdayEmailService’ -> Select Add
Reference -> from .Net tab, Select System.Configuaration -> click ADD).
Put the following code in the created app.config file –
<configuration>
<connectionStrings>
<add name="CustomerDBConnectionString"
connectionString="Data Source=RAMILU-PC\SQLEXPRESS;Initial Catalog=CustomerDB;Integrated Security=True;Pooling=False"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
Now let’s add a Service to the project –
1.
Right Click ‘BirthdayEmailService’ in
the Solution Explorer –> Select ‘Add New Item’.
2.
Select ‘Visual C# Items’ -> Select
Windows Service Template -> Give name – ‘BirthdayEmailService.cs’.
To Code against the EmailComponent (which we created earlier),
we got to add reference of it to our service.
1.
Right Click ‘References’ of
BirthdayEmailService –> Select ‘Add Reference’.
2.
Select ‘Browse’ tab -> Navigate to
the ‘EmaiComponent’ project folder -> Select the EmailComponent.dll in the
bin/Debug folder of ‘EmailComponent’ project. (NOTE: Before adding the
reference, build the EmailComponent Project so that it would be up to date.)
3.
Click OK.
One last thing which is left behind is to change the Entry point
of the application -
1.
Open Program.cs of the newly created
service.
2.
Replace the Main() function with the
following one –
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new BirthdayEmailService()
};
ServiceBase.Run(ServicesToRun);
}
Now, Writing code to BirthdayEmailService.cs –
1.
Open BirthdayEmailService.cs in
designer mode in VS 2010.
2.
Drag and drop an EventLog component and Timer component (Please do not
add this Timer component, I am adding this component from C# – Update :
1/16/2012) from
the ToolBox on to the designer.
3.
Change their names to eventLogEmail and scheduleTimer (check (2), please do not add Timer
component, I am adding this from C# – Update : 1/16/2012).
4.
EventLog is used to log the
activities of the service, and timer is used to make the service run at particular
intervals of time.
5.
Right click anywhere in the designer
surface -> Select -> View Code.
Write the following code –
§
Change the Settings/Properties as per
your own settings. Especially the Network Credentials and Username.
§
In the code, we first get the email
id’s (in DataSet) of all the customers who are celebrating their birthday on
that particular day, then we iterate through the through the DataSet and call
the SendEmailAsync() method of EmailComponent dll. SendEmailAsync() method then
process asynchronously and sends back the result.
§
We set the From Email, To Email,
subject, Message Body etc. properties in this routine and pass the same values
to the EmailComponent dll for further processing.
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Timers;
using System.Configuration;
using EmailComponent;
namespace BirthdayEmailService
{
partial class BirthdayEmailService : ServiceBase
{
private Timer scheduleTimer = null;
private DateTime lastRun;
private bool flag;
public BirthdayEmailService()
{
InitializeComponent();
if (!System.Diagnostics.EventLog.SourceExists("EmailSource"))
{
System.Diagnostics.EventLog.CreateEventSource("EmailSource", "EmailLog");
}
eventLogEmail.Source = "EmailSource";
eventLogEmail.Log = "EmailLog";
scheduleTimer = new Timer();
scheduleTimer.Interval = 1 * 5 * 60 * 1000;
scheduleTimer.Elapsed += new ElapsedEventHandler(scheduleTimer_Elapsed);
}
protected override void OnStart(string[] args)
{
flag = true;
lastRun = DateTime.Now;
scheduleTimer.Start();
eventLogEmail.WriteEntry("Started");
}
protected void scheduleTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (flag == true)
{
ServiceEmailMethod();
lastRun = DateTime.Now;
flag = false;
}
else if (flag == false)
{
if (lastRun.Date < DateTime.Now.Date)
{
ServiceEmailMethod();
}
}
}
private void ServiceEmailMethod()
{
eventLogEmail.WriteEntry("In Sending Email Method");
EmailComponent.GetEmailIdsFromDB getEmails = new EmailComponent.GetEmailIdsFromDB();
getEmails.connectionString = ConfigurationManager.ConnectionStrings["CustomerDBConnectionString"].ConnectionString;
getEmails.storedProcName = "GetBirthdayBuddiesEmails";
System.Data.DataSet ds = getEmails.GetMailIds();
EmailComponent.Email email = new EmailComponent.Email();
email.fromEmail = "example@gmail.com";
email.fromName = "example Name";
email.subject = "Birthday Wishes";
email.smtpServer = "smtp.gmail.com";
email.smtpCredentials = new System.Net.NetworkCredential("example@gmail.com", "example password");
foreach (System.Data.DataRow dr in ds.Tables[0].Rows)
{
email.messageBody = "<h4>Hello " + dr["CustomerName"].ToString() + "</h4><br/><h3>We Wish you a very Happy" +
"Birthday to You!!! Have a bash...</h3><br/><h4>Thank you.</h4>";
bool result = email.SendEmailAsync(dr["CustomerEmail"].ToString(), dr["CustomerName"].ToString());
if (result == true)
{
eventLogEmail.WriteEntry("Message Sent SUCCESS to - " + dr["CustomerEmail"].ToString() +
" - " + dr["CustomerName"].ToString());
}
else
{
eventLogEmail.WriteEntry("Message Sent FAILED to - " + dr["CustomerEmail"].ToString() +
" - " + dr["CustomerName"].ToString());
}
}
}
protected override void OnStop()
{
scheduleTimer.Stop();
eventLogEmail.WriteEntry("Stopped");
}
protected override void OnPause()
{
scheduleTimer.Stop();
eventLogEmail.WriteEntry("Paused");
}
protected override void OnContinue()
{
scheduleTimer.Start(); ;
eventLogEmail.WriteEntry("Continuing");
}
protected override void OnShutdown()
{
scheduleTimer.Stop();
eventLogEmail.WriteEntry("ShutDowned");
}
}
}
To install the created Service – We need to add installers, to
do that –
1.
Go to the Designer Pane of the
Service (BirthdayEmailService) -> Right Click in the Designer Pane ->
Select Add Installer.
Now in Design view for ProjectInstaller, Select
serviceInstaller1.
1.
Set the ServiceName property to
BirthdayEmailService. Set the StartType property to Automatic.
2.
Now Select ->
serviceProcessInstaller1 -> set its Account property to LocalSystem. This
will cause the service to be installed and to run on a local service account.
This completes the coding part of the Service. Now to install
Service, we got to create setup project –
1.
Right Click Solution -> Add ->
New Project
2.
Other Project Types -> Setup and
Deployment -> Visual Studio Installer –> Select ‘Setup’ Project.
3.
Name – BirthdayEmailServiceSetup
-> Click ADD.
To Add Project Output –
1.
Right Click ->
BirthdayEmailServiceSetup (in solution explorer) -> Add -> Project Output
2.
Select Primary Output (along with Service
name in the top DropDownList) -> click OK.
To Add Custom Actions –
1.
In Solution Explorer, right-click the
setup project, Select View, and then click Custom Actions.
2.
In the Custom Actions editor,
right-click the Custom Actions node and click Add Custom Action.
3.
In the opened Dialog, Double-click
the Application Folder in the list to open it, select Primary Output from
BirthdayEmailService(Active), and click OK.
The final Stage –
1.
Right Click the BirthdayEmailService
Project in the solutions explorer, and select Set As Startup Project.
2.
Then build the BirthdayEmailService
Project.
3.
Finally build the
BirthdayEmailServiceSetup project too.
The complete Folder structure would be -
On
successful build, Navigate to the physical location of the Setup Project
(BirthdayEmailServiceSetup) to find the exe file in the Debug Folder. Take the
EXE file and install it by double clicking it. On successful install, we can
find the service in the Systems Services Window -
1.
Go to Control Panel –>
Administrative Tools –> Services.
We can start the service by right clicking it and select start.
Similarly, we can stop it, pause it and continue it. The starting action of the
service is only required for initial time, later onwards on shutdown and
re-start, service will be automatically started.
To find
the EventLog Entries -
1.
Go to Control Panel –>
Administrative Tools –> Event Viewer –> Applications and Services Logs.
There we can find our EmailLog –
EventLog
logging Email Send Details – ***I tested the code with 5mins time interval.
Sample
Email in the Inbox -