Translate

How to create a Windows Service to run scripts using C# | Part 1

How to create a Windows Service to run scripts using C# | Part 1

In this article, I will be discussing as to how you could run a script as a Windows Service. Till now, I am sure you may have encountered certain situations where you will want to run a script periodically for a database update, API call etc. While this can be achieved using Cron Jobs in Linux, there are 2 ways to do this in Windows – either by using Windows Task Scheduler or by creating a Windows Service.

Here onwards this article will explain how you can use C# to create a Windows Service that will call a batch file and execute a PHP script. By using this, you can run any scripting language like PHP or a program.

Let’s jump right into coding, then!

Requirements

You can use any version of Microsoft Visual Studio as long as you have Windows Service Template available. You can also use the Visual Studio Express edition, but as Service Template and associated plug-ins will not available in this edition, you will have to configure them manually. In my case, I will be using Visual Studio 2012 and .Net framework 4.5

Open Visual Studio > New Project > Visual C# > Windows > Windows Service and enter an application name (for this tutorial I’m going to call it PHPWinService). Fill in the save location. Save the project, keeping the solution name as it is for now. Format the coding as per your preference.

VS 2012 new project

Microsoft Visual Studio will import all relevant libraries and create a template for you to start with.

Locate Service1.cs file from solution explorer, click once and change the file name to PHPWinService. Again move to solution explorer and double click on PHPWinService.cs, update (Name) and ServiceName to PHPWinService.

Click on PHPWinService class, It should look something like this:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;

namespace PHPWinService{

    public partial class PHPWinService : ServiceBase{

        public PHPWinService(){

            InitializeComponent();
        }

        protected override void OnStart(string[] args){

        }

        protected override void OnStop(){

        }
    }
}
Windows Service Template includes 4 main areas:

Library imports
Component initialization
Start and stop methods
Functions for Windows Service

Simply speaking, this is what happens when you start or stop a Windows Service once it is installed. Apart from these 4 main methods you can also create any customized method that you prefer in the class body (I will be doing this later on too, by the way).

Please note: "functions" are also called methods in this article and how you refer to them just varies from your personal programming background.

Next, in order to implement periodical calls to Windows Service we need to call Windows Timer and create a private variable to generate a predefined period:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Timers; //import system timer

namespace PHPWinService{

    public partial class PHPWinService : ServiceBase{

        //create a private timer variable
        private Timer _syncTimer = null;

        public PHPWinService(){

            InitializeComponent();
        }

        protected override void OnStart(string[] args){

        }

        protected override void OnStop(){

        }
    }
}
You may have noticed that the syncTimer variable is prefixed with an underscore (_). This is to indicate that it is a private variable. If I may suggest, I strongly recommend you to use these forms of potent strategies while programming so that it will be easier for you or any other programmer to debug your code in future, if ever it is needed.

Now, let's have a look at the OnStart method. As mentioned above this is the method that fires up when you start this service in Windows Services manager (Start > Control Panel > Administrative Tools > Services):
protected override void OnStart(string[] args){

     _syncTimer = new Timer();
     this._syncTimer.Interval = 600000;
     // for 10 mins = 10 x 60 x 1000 in milliseconds
     this._syncTimer.Elapsed += 
       new System.Timers.
         ElapsedEventHandler(this.syncTimerTicker);
     _syncTimer.Enabled = true;
}
I will not be explaining above code in detail as I assume that you will be able to understand it, if you already hail from a C# background. If not, please feel free to check out our C# beginner tutorials first.

ElapsedEventHandler is a private method, implemented to call processing batch file.

Now let's look at the OnStop method. In OnStop we are going to stop the timer on OnStart method:
protected override void OnStop(){

 _syncTimer.Enabled = false;

}
Looking good! It seems like we are almost there and now we just need to implement the method that we're calling on OnStart (syncTimerTick). This private method will call for the batch file which, in return shall call the PHP script that we need to run periodically:
private void syncTimerTick(object sender, EventArgs e){

   System.Diagnostics.Process.Start(@"c:\task.bat");
}
Let's combine everything together now! Before we do so, we need to first do a few changes on the settings of our project.

Go to the "Design" view in your application window or press shift + f7. You will see some values on the Properties window. Here, change the Name under Design to PHPWinService (which is the name of my current application)

Then under Miscellaneous Changes AutoLog to "true" and set ServiceName to PHPWinService. Note that this is very important as ServiceName is the value with which you can recognize your service once it is installed on the Services Manager.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Timers; //import system timer

namespace PHPWinService{

    public partial class PHPWinService : ServiceBase{

        //create a private timer variable
        private Timer _syncTimer = null;

        public PHPWinService(){

            InitializeComponent();
        }

        protected override void OnStart(string[] args){

            _syncTimer = new Timer();
            this._syncTimer.Interval = 600000;
            // for 10 mins = 10 x 60 x 1000 in milliseconds
            this._syncTimer.Elapsed += 
              new System.Timers.
                ElapsedEventHandler(this.syncTimerTicker);

            _syncTimer.Enabled = true;
        }

        protected override void OnStop(){

            _syncTimer.Enabled = false;
        }

        private void syncTimerTicker(object sender, EventArgs e){

            System.Diagnostics.Process.Start(@"c:\task.bat");
        }
    }
}

Adding the installer

Now that we have completed the C# coding for this project, it is time to create an installer. To do this:

Click on PHPWinService.cs[Design] tab and right click on main window, from pop up select "Add Installer".

VS 2012 Add Installer

A component class that contains two installers will be added to your project, by default. The component named ProjectInstaller, and the 2 installers that it contains are each for windiws service installer and associated processes,

Under ProjectInstaller.cs[Design] tab, click "serviceInstaller1", rename it to PHPWinService from Properties/Solution Explorer((Name), DisplayName and ServiceName needs to be updated), set the StartType to Automatic and add a simple description about the service in Description.

Click "serviceProcessInstaller1", rename it to "PHPWinServiceProcess" and set the Account Property to LocalSystem. This will thereby install the service and run over a local service account. Finally, you can build the project as a release version.


Visual Studio Solution Explorer


In the next article, we will go through on how to use installutil to perform a manual service installation/uninstallation.

Related post -
How to create a Windows Service to run scripts using C# | Part 2
How to create a Windows Service to run scripts using C# | Part 3
How to create a setup wrapper with Microsoft Visual Studio

No comments:

Post a Comment

Nerdcore is a free tutorial website about latest technological development, designing and programming. Nerdcore have tuts for all skill levels in web, desktop and mobile application development. Tuts and courses we provided are carefully crafted by expert developers and designers from www.waan.it