In this article I will explain a tutorial to create a simple Windows Service with sample example in C# and VB.Net.
The Windows service will support two modes:
1. Interval mode: where Windows Service execute a task at regular intervals after some delay
2. Daily mode: where the Windows Service will execute a task at specific (certain) time of day.
 
 

Creating a Windows Service Project

Let’s get started with creating your new project of type Windows Service.
1. Open Visual Studio and click on Create a New Project.
Tutorial to create a simple Windows Service with sample example in C# and VB.Net
 
2. From the Create a new project Dialog window, select Windows Service option.
Tutorial to create a simple Windows Service with sample example in C# and VB.Net
 
3. Then, you need to set a suitable Name for your project and also you can set its Location where you want to create the Project and you need to select .NET Framework 4.8 from Framework option.
Tutorial to create a simple Windows Service with sample example in C# and VB.Net
 
Once the project has been created then, you will need to copy the following appSettings to the App.Config file.
Mode: It is used to set the Mode. There are two types of modes namely Daily and Interval.
IntervalMinutes: It is used when Mode is set to Interval. It consists of the Interval value in Minutes after which the Windows Service will perform a task. In other words, it is the delay value.
ScheduledTime: This setting is used when the Mode is set to Daily. It is used to notify the Windows Service the time it should perform a task. The value specified is in 24-hour time format.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <appSettings>
        <add key="Mode" value="Interval"/>
        <!-- <add key ="Mode" value ="Daily"/>-->
        <add key="IntervalMinutes" value="1"/>
        <add key="ScheduledTime" value="19:45"/>
    </appSettings>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
    </startup>
</configuration>
 
 

Namespaces

You will need to import the following namespaces.
C#
using System.IO;
using System.Threading;
using System.Configuration;
 
VB.Net
Imports System.IO
Imports System.Threading
Imports System.Configuration
 
 

Timer Configuration

The Service class has been assigned with the OnStart and OnStop event handlers.

OnStart

Inside the OnStart event handler, the message is set using WriteToFile method (explained later) and then ScheduleService method (explained later) is called.
 

OnStop

Inside the OnStop event handler, the message is set using WriteToFile method (explained later) and then Dispose method (explained later) is called using Timer class.
The private property of Timer has been defined.
Note: A Timer refers to a utility class that allows you to schedule tasks to run after a certain delay or periodically. It can be used to execute code after a specified time interval, making it useful for tasks like repeating an action, triggering events after a delay, or scheduling operations in background threads.
 

ScheduleService

Inside the ScheduleService method, a Try-Catch block is initialized.
Inside the try block, a variable is initialized where the SchedularCallback method (explained later) is passed to the TimerCallback class.
Then, the mode is set and the message is set using WriteToFile method (explained later).
 

SchedularCallback

Inside the SchedularCallback method, the message is set using WriteToFile method (explained later) and then ScheduleService method is called.
 

WriteToFile

The WriteToFile method accepts string as a parameter.
Inside this method, a Text file is accessed where the path is set and StreamWriter class is created where the path is passed as a parameter.
Then, using the WriteLine method of writer class the string and current DateTime is displayed.
Note: The second parameter is passed as TRUE to the StreamWriter class, so that the contents are appended to the Text file.
 
When the Windows Service starts, it calls the ScheduleService method which first reads the Mode settings from the AppSettings. There’s a ScheduledTime variable which is set in both modes.
When the Mode is Daily then, the ScheduledTime is read from the AppSettings and when the scheduled time is passed, it is updated to same time on the next day.
When the Mode is set to Interval then, the IntervalMinutes is read from the AppSettings and the schedule time is calculated by adding the Interval Minutes to the Current Time.
Finally, the Timer is set to run the scheduled time. When the scheduled time is elapsed, the Timer’s Callback method is triggered which logs the current date and time to a Text file.
Note: While using the above code, you could encounter the following error:

The type or namespace name 'ConfigurationManager' does not exist in the namespace 'System.Configuration' (are you missing an assembly reference?).

The solution is provided in my article The type or namespace name 'ConfigurationManager' does not exist in the namespace 'System.Configuration’.
 
C#
public partial class Service1 : ServiceBase
{
    public Service1()
    {
        InitializeComponent();
    }
 
    protected override void OnStart(string[]args)
    {
        this.WriteToFile("Simple Service started {0}");
        this.ScheduleService();
    }
 
    protected override void OnStop()
    {
        this.WriteToFile("Simple Service stopped {0}");
        this.Schedular.Dispose();
    }
 
    private Timer Schedular;
 
    public void ScheduleService()
    {
        try
        {
            Schedular = new Timer(new TimerCallback(SchedularCallback));
            string mode = ConfigurationManager.AppSettings["Mode"].ToUpper();
            this.WriteToFile("Simple Service Mode: " + mode +" {0}");
 
            //Set the Default Time.
            DateTime scheduledTime DateTime.MinValue;
 
            if  (mode == "DAILY")
            {
                //Get the Scheduled Time from AppSettings.
                scheduledTime DateTime.Parse(System.Configuration.ConfigurationManager.AppSettings["ScheduledTime"]);
                if (DateTime.Now > scheduledTime)
                {
                    //If Scheduled Time is passed set Schedule for the next day.
                    scheduledTime scheduledTime.AddDays(1);
                }
            }
 
            if (mode.ToUpper() == "INTERVAL")
            {
                //Get the Interval in Minutes from AppSettings.
                int intervalMinutes Convert.ToInt32(ConfigurationManager.AppSettings["IntervalMinutes"]);
 
                //Set the Scheduled Time by adding the Interval to Current Time.
                scheduledTime DateTime.Now.AddMinutes(intervalMinutes);
                if (DateTime.Now > scheduledTime)
                {
                    //If Scheduled Time is passed set Schedule for the next Interval.
                    scheduledTime scheduledTime.AddMinutes(intervalMinutes);
                }
            }
 
            TimeSpan timeSpan scheduledTime.Subtract(DateTime.Now);
            string schedule = string.Format("{0} day(s) {1} hour(s) {2} minute(s) {3} seconds(s)", timeSpan.Days, timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds);
 
            this.WriteToFile("Simple Service scheduled to run after: " + schedule + " {0}");
 
            //Get the difference in Minutes between the Scheduled and Current Time.
            int dueTime Convert.ToInt32(timeSpan.TotalMilliseconds);
 
            //Change the Timer's Due Time.
            Schedular.Change(dueTime, Timeout.Infinite);
        }
        catch (Exception ex)
        {
            this.WriteToFile("Simple Service Error on: {0} " + ex.Message + ex.StackTrace);
 
            //Stop the Windows Service.
            using (System.ServiceProcess.ServiceController serviceController = new System.ServiceProcess.ServiceController("SimpleService"))
            {
                serviceController.Stop();
            }
        }
    }
 
    private void SchedularCallback(object e)
    {
        this.WriteToFile("Simple Service Log: {0}");
        this.ScheduleService();
    }
 
    private void WriteToFile(string text)
    {
        string  path = "C:\\ServiceLog.txt";
        using (StreamWriter writer = new StreamWriter(path, true))
        {
            writer.WriteLine(string.Format(text, DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt")));
            writer.Close();
        }
    }
}
 
VB.Net
Public Class Service1
 
    Protected Overrides Sub OnStart(ByVal args() As String)
        Me.WriteToFile("Simple Service started at " + DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt"))
        Me.ScheduleService()
    End Sub
 
    Protected Overrides Sub OnStop()
        Me.WriteToFile("Simple Service stopped at " + DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt"))
        Me.Schedular.Dispose()
    End Sub
 
    Private Schedular As Timer
 
    Public Sub ScheduleService()
        Try
            Schedular = New Timer(New TimerCallback(AddressOf SchedularCallback))
            Dim mode As String ConfigurationManager.AppSettings("Mode").ToUpper()
            Me.WriteToFile((Convert.ToString("Simple Service Mode: ") & mode) + " {0}")
 
            'Set the Default Time.
            Dim scheduledTime As DateTime DateTime.MinValue
 
            If  mode = "DAILY" Then
                'Get the Scheduled Time from AppSettings.
                scheduledTime DateTime.Parse(System.Configuration.ConfigurationManager.AppSettings("ScheduledTime"))
                If DateTime.Now > scheduledTime Then
                    'If Scheduled Time is passed set Schedule for the next day.
                    scheduledTime scheduledTime.AddDays(1)
                End If
            End If
 
            If mode.ToUpper() = "INTERVAL" Then
                'Get the Interval in Minutes from AppSettings.
                Dim intervalMinutes As Integer Convert.ToInt32(ConfigurationManager.AppSettings("IntervalMinutes"))
 
                'Set the Scheduled Time by adding the Interval to Current Time.
                scheduledTime DateTime.Now.AddMinutes(intervalMinutes)
                If DateTime.Now > scheduledTime Then
                    'If Scheduled Time is passed set Schedule for the next Interval.
                    scheduledTime scheduledTime.AddMinutes(intervalMinutes)
                End If
            End If
 
            Dim timeSpan As TimeSpan scheduledTime.Subtract(DateTime.Now)
            Dim schedule As String = String.Format("{0} day(s) {1} hour(s) {2} minute(s) {3} seconds(s)", timeSpan.Days, timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds)
 
            Me.WriteToFile((Convert.ToString("Simple Service scheduled to run after: ") & schedule) + " {0}")
 
            'Get the difference in Minutes between the Scheduled and Current Time.
            Dim dueTime As Integer Convert.ToInt32(timeSpan.TotalMilliseconds)
 
            'Change the Timer's Due Time.
            Schedular.Change(dueTime, Timeout.Infinite)
        Catch  ex As Exception
            WriteToFile("Simple Service Error on: {0} " + ex.Message + ex.StackTrace)
 
            'Stop the Windows Service.
            Using serviceController As New System.ServiceProcess.ServiceController("SimpleService")
                serviceController.[Stop]()
            End Using
        End Try
    End Sub
 
    Private Sub SchedularCallback(e As Object)
        Me.WriteToFile("Simple Service Log: " + DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt"))
        Me.ScheduleService()
    End Sub
 
    Private Sub WriteToFile(text As String)
        Dim path As String "C:\ServiceLog.txt"
        Using writer As New StreamWriter(path, True)
            writer.WriteLine(String.Format(text, DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt")))
            writer.Close()
        End Using
    End Sub
End Class
 
 

Adding an Installer to the Windows Service

Once the Windows Service is ready, the Installer class is added to the Windows Service as it is necessary for the Windows Service installation.
Following are the steps to add Installer class.
1. Right Click the Service1.cs class and click View Designer in the context menu.
Tutorial to create a simple Windows Service with sample example in C# and VB.Net
2. Once the Design View is show, you need to right click and then select Add Installer in the context menu.
Tutorial to create a simple Windows Service with sample example in C# and VB.Net
 
 

Setting the Windows Service Name and StartType

The above action will add an Installer class named ProjectInstaller. The next task is to open the ProjectInstaller.Designer class and look for InitializeComponent Method.
In this method, the ServiceName of the Windows Service is modified and its StartType is set to Automatic, so that along with the computer the Windows Service will start automatically.
Note: If you don’t set the StartType to Automatic, the default value is Manual and hence the Windows Service will not start automatically when the machine is started.
 
C#
private void InitializeComponent()
{
    this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();
    this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();
    //
    // serviceProcessInstaller1
    //
    this.serviceProcessInstaller1.Password = null;
    this.serviceProcessInstaller1.Username = null;
    //
    // serviceInstaller1
    //
    this.serviceInstaller1.ServiceName "SimpleService";
    this.serviceInstaller1.StartType System.ServiceProcess.ServiceStartMode.Automatic;
    //
    //ProjectInstaller
    //
    this.Installers.AddRange(new System.Configuration.Install.Installer[] {
    this.serviceProcessInstaller1,
    this.serviceInstaller1});
}
 
VB.Net
Private Sub InitializeComponent()
    Me.ServiceProcessInstaller1 = New System.ServiceProcess.ServiceProcessInstaller()
    Me.ServiceInstaller1 = New System.ServiceProcess.ServiceInstaller()
    '
    'ServiceProcessInstaller1
    '
    Me.ServiceProcessInstaller1.Password = Nothing
    Me.ServiceProcessInstaller1.Username = Nothing
    '
    'ServiceInstaller1
    '
    'Set the ServiceName of the Windows Service.
    Me.ServiceInstaller1.ServiceName "SimpleService"
 
    'Set its StartType to Automatic.
    Me.ServiceInstaller1.StartType System.ServiceProcess.ServiceStartMode.Automatic
 
    '
    'ProjectInstaller
    '
    Me.Installers.AddRange(New System.Configuration.Install.Installer()   { Me.ServiceProcessInstaller1, Me.ServiceInstaller1})
End Sub
 
 

Making the Windows Service Automatically start after Installation

After the installation, the Windows Service needs to be started manually through the Services section of My Computer Management.
It can also be started automatically after installation by making use of the AfterInstall event handler which triggers immediately after Windows Service is installed.
Inside the ProjectInstaller class, the AfterInstall event handler is overridden and the add the code to start the Windows Service is added to it.
C#
[RunInstaller(true)]
public partial class ProjectInstaller : System.Configuration.Install.Installer
{
    public ProjectInstaller()
    {
        InitializeComponent();
    }
 
    protected override void OnAfterInstall(IDictionary savedState)
    {
        base.OnAfterInstall(savedState);
 
        //The following code starts the services after it is installed.
        using (System.ServiceProcess.ServiceController serviceController = new System.ServiceProcess.ServiceController(serviceInstaller1.ServiceName))
        {
            serviceController.Start();
        }
    }
}
 
VB.Net
Public Class ProjectInstaller
    Public Sub New()
        MyBase.New()
        'This call is required by the Component Designer.
        InitializeComponent()
        'Add initialization code after the call toInitializeComponent
    End Sub
    Protected Overrides Sub OnAfterInstall(savedState As IDictionary)
        MyBase.OnAfterInstall(savedState)
        'The following code starts the services after it is installed.
        Using serviceController As New System.ServiceProcess.ServiceController(ServiceInstaller1.ServiceName)
            serviceController.Start()
        End Using
    End Sub
End Class
 
 

Installing the Windows Service using InstallUtil.exe

Once all the processes are complete, we can now build the Windows Service. Once the Windows Service is build you need to find the EXE file in the Debug folder of the Project.
Note: Once the Windows Service is ready for deployment, it is recommended to make use of the Release version of the EXE file instead of the Debug version.
 
To find the EXE, simply right click Project and select Open Folder in Windows Explorer. Now navigate to Bin => Debug folder and look for the EXE file with name same as that of the project.
Tutorial to create a simple Windows Service with sample example in C# and VB.Net
 
Now copy and build the path in a Notepad (Text) file.
Note: I would recommend to build the command in a Notepad and save it somewhere so that you can use it multiple times.
 

InstallUtil Syntax

InstallUtil /i
 
Example:
InstallUtil /i C:\Users\Mudassar\Projects\WindowsService\bin\Debug\WindowsService.exe
 
Now you need to open Programs => Microsoft Visual Studio 2010 => Visual Studio Tools => Visual Studio Command Prompt (2010).
Note: I am making use of Visual Studio 2010, and hence you need to use the appropriate version installed on your computer. And make sure you are logged in as Administrator. Without Administrator rights it would not allow you to install the Windows Service.
 
In the command prompt window, copy the InstallUtil command from Notepad and right click in the Command Prompt and click Paste and then press Enter key.
Tutorial to create a simple Windows Service with sample example in C# and VB.Net
 
Now the Installer will ask for Logon permissions to run the Windows Service and hence you will need to add Windows Username and Password of user who has appropriate permission.
Tutorial to create a simple Windows Service with sample example in C# and VB.Net
 
Note: Username must include Domain Name or the Computer name.
 
After successful installation you will see the following message.
Tutorial to create a simple Windows Service with sample example in C# and VB.Net
 
You can find the Windows Service in the Services window. In order to open Services window in the Run Command type, services.msc and hit enter.
Tutorial to create a simple Windows Service with sample example in C# and VB.Net
 
 

Uninstalling the Windows Service using InstallUtil.exe

The syntax for uninstalling a Windows Service is very similar to the installation syntax.

InstallUtil Syntax

InstallUtil /u
 
Example:
InstallUtil /u C:\Users\Mudassar\Projects\WindowsService\bin\Debug\WindowsService.exe
 
After successful uninstallation you will see the following message.
Tutorial to create a simple Windows Service with sample example in C# and VB.Net
 
 

Downloads