Introduction
When I was given the task to create the Windows service for the first time, I faced all sorts of issues and almost gave up. In this article, I will show you how you can configure your Windows service to start automatically after installation and do some useful task in the background.
Background
While writing the article, I am assuming that you know what the Windows service is and the benefits of using it. This is not the detailed tutorial for explaining each and everything about the Windows services but in the end, you will be able to structure Windows services really quickly. I do that in about 5 minutes now. So let's get started.
Using the Code
I am using Visual Studio 2013 to develop the Windows service. Open Visual Studio, click on File->New->Project and create the Windows Service project.
It will present you with the [Design] of automatically created Service1.cs (Rename the file name if you want but for demo purposes, I will continue with the name Service1
), right click anywhere on the design and click 'Add Installer'.
After you click on Add Installer, it will create the file ProjectInsaller.cs and open it in [Design] mode with the ServiceInstaller
and ServiceProcessInstaller
. Save the file. Now, right click on ServiceInstaller1
and click properties.
Go to the Properties window and edit the properties. Update the Display Name/Description properties to whatever you want to show in the Service.msc listing. Change the StartType to Automatic if you want it to start automatically on Windows startups. Do not change the Parent [ProjectInstaller]
. Save the properties.
Now, go back to the ProjectInstaller.cs [Design] window, and this time, select serviceProcessInstaller1
, go to its properties. You only have to change the Account. I normally write Windows services under Local Services. You can find articles on which account you should choose.
Let's write some code now. Open Service1.cs, you will find two methods there, i.e., OnStart
and OnStop
. As the names suggests, OnStart
is called whenever the service starts and OnStop
when the service stops. Windows services are written for long running tasks in the background so you would need to keep it alive. In order to do that, we use a Timer
which will call itself after x seconds.
Declare the Timer
object in your service1.cs:
private System.Timers.Timer timer;
Initialize it inside the constructor:
timer = new Timer(30000D); timer.AutoReset = true;
timer.Elapsed += new ElapsedEventHandler(timer_elasped);
Now, in your OnStart
function, you need to start the timer to keep the service alive.
try
{
timer.Start();
}
catch (Exception ex)
{
}
and stop the timer in OnStop
function with:
timer.Stop();
Declare the event handler for your timer
. The main operations that your service should perform must go inside this handler.
private void timer_elasped(object sender, ElapsedEventArgs e)
{
}
With the basic structure done, we would now move on to configure it to start automatically after installation because you don't wan't the user to restart the machine to start your service. We should always start it immediately depending upon the requirement.
Go to the Program.cs and add the using
s statement to reference the required classes:
using System.Configuration.Install;
Inside the main function, add try catch
block and paste the following code inside try
block:
if (Environment.UserInteractive)
ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location });
else
ServiceBase.Run(new Service1());
After that is done, you need to tell the service to run automatically once the installation will be done. Open ProjectInstaller.cs code and add the appropriate references.
using System.ComponentModel;
using System.Configuration.Install;
using System.Diagnostics;
using System.ServiceProcess;
Then paste the following methods:
private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e)
{
try
{
using (ServiceController sc = new ServiceController
(serviceInstaller1.ServiceName, Environment.MachineName))
{
if (sc.Status != ServiceControllerStatus.Running)
sc.Start();
}
}
catch (Exception ee)
{
EventLog.WriteEntry("Application", ee.ToString(), EventLogEntryType.Error);
}
}
private void serviceInstaller1_Committed(object sender, InstallEventArgs e)
{
try
{
using (ServiceController sc = new ServiceController(serviceInstaller1.ServiceName))
{
SetRecoveryOptions(sc.ServiceName);
}
}
catch (Exception e1)
{
EventLog.WriteEntry("Application", e1.ToString(), EventLogEntryType.Error);
return;
}
}
static void SetRecoveryOptions(string serviceName)
{
int exitCode;
using (var process = new Process())
{
var startInfo = process.StartInfo;
startInfo.FileName = "sc";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = string.Format
("failure \"{0}\" reset= 0 actions= restart/60000", serviceName);
process.Start();
process.WaitForExit();
exitCode = process.ExitCode;
}
if (exitCode != 0)
throw new InvalidOperationException();
}
Last step in the process is, hookup these events with the serviceInstaller
. To do that, open the ProjectInstaller.cs [Design]. Go to the Properties, Select Events and paste the event handler names for AfterInstall and Committed events.
In the end, just to test whether or not everything went smoothly, copy the bin folder from your default Visual Studio Project Directory (if it's on same drive as your Windows drive) and paste it on some other drive. Right click on your application.exe file and run it as ADMINISTRATOR. To verify whether or not it's installed and running, click Window+R and type services.msc, press enter, it will open up the window listing all the installed services. Now, search for your service name and see if it's installed and running.
In the end, if you want to remove the Windows Service from your machine, open command prompt as administrator, go to the path from where you installed it and type in:
sc delete ServiceName
Good luck.
History
- 7th September, 2015: Initial version