Tutorial: Create a Windows service app

This article demonstrates how to create a Windows service app in Visual Studio that writes letters to an consequence log.

Create a service

To begin, create the project and set the values that are required for the service to function correctly.

  1. From the Visual Studio File menu, select New > Project (or press Ctrl+Shift+N) to open the New Projection window.

  2. Find and select the Windows Service (.NET Framework) project template.

    Note

    If yous don't see the Windows Service template, you may need to install the .Net desktop development workload using Visual Studio Installer.

  3. For Proper name, enter MyNewService, and then select OK.

    The Design tab appears (Service1.cs [Design] or Service1.vb [Design]).

    The projection template includes a component form named Service1 that inherits from System.ServiceProcess.ServiceBase. It includes much of the bones service code, such as the lawmaking to beginning the service.

Rename the service

Rename the service from Service1 to MyNewService.

  1. In Solution Explorer, select Service1.cs or Service1.vb, and choose Rename from the shortcut menu. Rename the file to MyNewService.cs or MyNewService.vb, and so printing Enter

    A popular-up window appears request whether y'all would like to rename all references to the code chemical element Service1.

  2. In the pop-up window, select Yes.

    Rename prompt

  3. In the Design tab, select Backdrop from the shortcut menu. From the Properties window, change the ServiceName value to MyNewService.

    Service properties

  4. Select Save All from the File menu.

Add features to the service

In this department, y'all add a custom event log to the Windows service. The EventLog component is an example of the type of component you can add together to a Windows service.

Add custom event log functionality

  1. In Solution Explorer, from the shortcut menu for MyNewService.cs or MyNewService.vb, choose View Designer.

  2. In Toolbox, expand Components, so drag the EventLog component to the Service1.cs [Blueprint] or Service1.vb [Design] tab.

  3. In Solution Explorer, from the shortcut menu for MyNewService.cs or MyNewService.vb, cull View Code.

  4. Ascertain a custom event log.

    For C#, edit the existing MyNewService() constructor as shown in the following code snippet. For Visual Basic, add together the New() constructor as shown in the post-obit lawmaking snippet.

                      public MyNewService() {     InitializeComponent();     eventLog1 = new Organization.Diagnostics.EventLog();     if (!System.Diagnostics.EventLog.SourceExists("MySource"))     {         Organisation.Diagnostics.EventLog.CreateEventSource(             "MySource","MyNewLog");     }     eventLog1.Source = "MySource";     eventLog1.Log = "MyNewLog"; }                                  
                      ' To access the constructor in Visual Bones, select New from the ' method proper name drib-down list.  Public Sub New()     MyBase.New()     InitializeComponent()     Me.EventLog1 = New System.Diagnostics.EventLog     If Not System.Diagnostics.EventLog.SourceExists("MySource") Then         Organization.Diagnostics.EventLog.CreateEventSource("MySource",         "MyNewLog")     Terminate If     EventLog1.Source = "MySource"     EventLog1.Log = "MyNewLog" End Sub                                  
  5. Add together a using statement to MyNewService.cs (if it doesn't already exist), or an Imports statement to MyNewService.vb, for the System.Diagnostics namespace:

                      using System.Diagnostics;                                  
                      Imports System.Diagnostics                                  
  6. Select Relieve All from the File menu.

Define what occurs when the service starts

In the code editor for MyNewService.cs or MyNewService.vb, locate the OnStart method. Visual Studio automatically created an empty method definition when you created the project. Add code that writes an entry to the event log when the service starts:

              protected override void OnStart(string[] args) {     eventLog1.WriteEntry("In OnStart."); }                          
              ' To access the OnStart in Visual Basic, select OnStart from the ' method proper name drib-down listing.  Protected Overrides Sub OnStart(ByVal args() As String)     EventLog1.WriteEntry("In OnStart") End Sub                          

Polling

Because a service application is designed to be long-running, it unremarkably polls or monitors the system, which you prepare up in the OnStart method. The OnStart method must return to the operating system later on the service's operation has begun and then that the organisation isn't blocked.

To set upward a simple polling mechanism, use the System.Timers.Timer component. The timer raises an Elapsed event at regular intervals, at which time your service can do its monitoring. Y'all utilise the Timer component as follows:

  • Set the properties of the Timer component in the MyNewService.OnStart method.
  • Starting time the timer by calling the Start method.
Set upward the polling mechanism
  1. Add together the following code in the MyNewService.OnStart event to set upwards the polling mechanism:

                      // Set up up a timer that triggers every minute. Timer timer = new Timer(); timer.Interval = 60000; // sixty seconds timer.Elapsed += new ElapsedEventHandler(this.OnTimer); timer.Outset();                                  
                      ' Gear up a timer that triggers every minute. Dim timer Every bit Timer = New Timer() timer.Interval = 60000 ' sixty seconds AddHandler timer.Elapsed, AddressOf Me.OnTimer timer.Start()                                  
  2. Add together a using statement to MyNewService.cs, or an Imports statement to MyNewService.vb, for the Organisation.Timers namespace:

                      using Organization.Timers;                                  
                      Imports Organization.Timers                                  
  3. In the MyNewService grade, add the OnTimer method to handle the Timer.Elapsed result:

                      public void OnTimer(object sender, ElapsedEventArgs args) {     // TODO: Insert monitoring activities here.     eventLog1.WriteEntry("Monitoring the System", EventLogEntryType.Data, eventId++); }                                  
                      Private Sub OnTimer(sender As Object, due east As Timers.ElapsedEventArgs)    ' TODO: Insert monitoring activities here.    eventLog1.WriteEntry("Monitoring the Organization", EventLogEntryType.Data, eventId)    eventId = eventId + 1 End Sub                                  
  4. In the MyNewService class, add a member variable. Information technology contains the identifier of the next event to write into the event log:

                      private int eventId = 1;                                  
                      Private eventId As Integer = 1                                  

Instead of running all your work on the master thread, you can run tasks by using background worker threads. For more than information, meet System.ComponentModel.BackgroundWorker.

Define what occurs when the service is stopped

Insert a line of code in the OnStop method that adds an entry to the event log when the service is stopped:

              protected override void OnStop() {     eventLog1.WriteEntry("In OnStop."); }                          
              Protected Overrides Sub OnStop()     EventLog1.WriteEntry("In OnStop.") End Sub                          

Ascertain other actions for the service

You lot can override the OnPause, OnContinue, and OnShutdown methods to define boosted processing for your component.

The following code shows how you to override the OnContinue method in the MyNewService form:

              protected override void OnContinue() {     eventLog1.WriteEntry("In OnContinue."); }                          
              Protected Overrides Sub OnContinue()     EventLog1.WriteEntry("In OnContinue.") Finish Sub                          

Set up service condition

Services written report their condition to the Service Control Manager and then that a user can tell whether a service is performance correctly. By default, a service that inherits from ServiceBase reports a limited set of status settings, which include SERVICE_STOPPED, SERVICE_PAUSED, and SERVICE_RUNNING. If a service takes a while to start up, information technology's useful to report a SERVICE_START_PENDING condition.

You tin can implement the SERVICE_START_PENDING and SERVICE_STOP_PENDING status settings by adding code that calls the Windows SetServiceStatus office.

Implement service awaiting status

  1. Add together a using statement to MyNewService.cs, or an Imports statement to MyNewService.vb, for the System.Runtime.InteropServices namespace:

                      using Organization.Runtime.InteropServices;                                  
                      Imports System.Runtime.InteropServices                                  
  2. Add together the following code to MyNewService.cs, or MyNewService.vb, to declare the ServiceState values and to add a structure for the status, which y'all'll use in a platform invoke call:

                      public enum ServiceState {     SERVICE_STOPPED = 0x00000001,     SERVICE_START_PENDING = 0x00000002,     SERVICE_STOP_PENDING = 0x00000003,     SERVICE_RUNNING = 0x00000004,     SERVICE_CONTINUE_PENDING = 0x00000005,     SERVICE_PAUSE_PENDING = 0x00000006,     SERVICE_PAUSED = 0x00000007, }  [StructLayout(LayoutKind.Sequential)] public struct ServiceStatus {     public int dwServiceType;     public ServiceState dwCurrentState;     public int dwControlsAccepted;     public int dwWin32ExitCode;     public int dwServiceSpecificExitCode;     public int dwCheckPoint;     public int dwWaitHint; };                                  
                      Public Enum ServiceState     SERVICE_STOPPED = 1     SERVICE_START_PENDING = two     SERVICE_STOP_PENDING = 3     SERVICE_RUNNING = four     SERVICE_CONTINUE_PENDING = 5     SERVICE_PAUSE_PENDING = 6     SERVICE_PAUSED = vii End Enum  <StructLayout(LayoutKind.Sequential)> Public Construction ServiceStatus     Public dwServiceType As Long     Public dwCurrentState As ServiceState     Public dwControlsAccepted Every bit Long     Public dwWin32ExitCode Equally Long     Public dwServiceSpecificExitCode As Long     Public dwCheckPoint As Long     Public dwWaitHint As Long End Structure                                  

    Note

    The Service Control Managing director uses the dwWaitHint and dwCheckpoint members of the SERVICE_STATUS structure to make up one's mind how much fourth dimension to expect for a Windows service to start or close down. If your OnStart and OnStop methods run long, your service tin request more time by calling SetServiceStatus over again with an incremented dwCheckPoint value.

  3. In the MyNewService class, declare the SetServiceStatus function by using platform invoke:

                      [DllImport("advapi32.dll", SetLastError = true)] private static extern bool SetServiceStatus(System.IntPtr handle, ref ServiceStatus serviceStatus);                                  
                      Declare Auto Function SetServiceStatus Lib "advapi32.dll" (ByVal handle As IntPtr, ByRef serviceStatus As ServiceStatus) As Boolean                                  
  4. To implement the SERVICE_START_PENDING condition, add together the post-obit code to the starting time of the OnStart method:

                      // Update the service country to Start Awaiting. ServiceStatus serviceStatus = new ServiceStatus(); serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING; serviceStatus.dwWaitHint = 100000; SetServiceStatus(this.ServiceHandle, ref serviceStatus);                                  
                      ' Update the service state to Get-go Pending. Dim serviceStatus As ServiceStatus = New ServiceStatus() serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING serviceStatus.dwWaitHint = 100000 SetServiceStatus(Me.ServiceHandle, serviceStatus)                                  
  5. Add code to the end of the OnStart method to set the status to SERVICE_RUNNING:

                      // Update the service state to Running. serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING; SetServiceStatus(this.ServiceHandle, ref serviceStatus);                                  
                      ' Update the service state to Running. serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING SetServiceStatus(Me.ServiceHandle, serviceStatus)                                  
  6. (Optional) If OnStop is a long-running method, repeat this process in the OnStop method. Implement the SERVICE_STOP_PENDING status and return the SERVICE_STOPPED status before the OnStop method exits.

    For instance:

                      // Update the service state to Cease Pending. ServiceStatus serviceStatus = new ServiceStatus(); serviceStatus.dwCurrentState = ServiceState.SERVICE_STOP_PENDING; serviceStatus.dwWaitHint = 100000; SetServiceStatus(this.ServiceHandle, ref serviceStatus);  // Update the service state to Stopped. serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED; SetServiceStatus(this.ServiceHandle, ref serviceStatus);                                  
                      ' Update the service state to Finish Pending. Dim serviceStatus As ServiceStatus = New ServiceStatus() serviceStatus.dwCurrentState = ServiceState.SERVICE_STOP_PENDING serviceStatus.dwWaitHint = 100000 SetServiceStatus(Me.ServiceHandle, serviceStatus)  ' Update the service land to Stopped. serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED SetServiceStatus(Me.ServiceHandle, serviceStatus)                                  

Add installers to the service

Before you run a Windows service, you demand to install information technology, which registers it with the Service Control Manager. Add installers to your projection to handle the registration details.

  1. In Solution Explorer, from the shortcut menu for MyNewService.cs, or MyNewService.vb, choose View Designer.

  2. In the Design view, select the background area, and so cull Add Installer from the shortcut carte du jour.

    By default, Visual Studio adds a component grade named ProjectInstaller, which contains ii installers, to your projection. These installers are for your service and for the service's associated process.

  3. In the Design view for ProjectInstaller, select serviceInstaller1 for a Visual C# project, or ServiceInstaller1 for a Visual Basic project, then choose Properties from the shortcut carte du jour.

  4. In the Properties window, verify the ServiceName belongings is gear up to MyNewService.

  5. Add text to the Description belongings, such as A sample service.

    This text appears in the Description cavalcade of the Services window and describes the service to the user.

    Service description in the Services window.

  6. Add together text to the DisplayName holding. For instance, MyNewService Display Name.

    This text appears in the Display Name column of the Services window. This name can be unlike from the ServiceName property, which is the proper noun the system uses (for example, the proper noun you utilise for the net start control to start your service).

  7. Gear up the StartType property to Automatic from the drop-down listing.

  8. When you're finished, the Properties windows should look like the post-obit figure:

    Installer Properties for a Windows service

  9. In the Blueprint view for ProjectInstaller, cull serviceProcessInstaller1 for a Visual C# project, or ServiceProcessInstaller1 for a Visual Basic project, then choose Backdrop from the shortcut menu. Set the Account property to LocalSystem from the drop-downwardly list.

    This setting installs the service and runs it by using the local system business relationship.

    Important

    The LocalSystem account has broad permissions, including the ability to write to the event log. Apply this account with circumspection, because it might increment your risk of attacks from malicious software. For other tasks, consider using the LocalService account, which acts as a non-privileged user on the local calculator and presents anonymous credentials to any remote server. This example fails if you attempt to use the LocalService business relationship, considering it needs permission to write to the event log.

For more data most installers, meet How to: Add installers to your service awarding.

(Optional) Set startup parameters

Annotation

Before you decide to add together startup parameters, consider whether it'southward the best manner to pass information to your service. Although they're easy to utilize and parse, and a user tin easily override them, they might be harder for a user to notice and apply without documentation. Generally, if your service requires more than merely a few startup parameters, you should use the registry or a configuration file instead.

A Windows service can accept command-line arguments, or startup parameters. When you add lawmaking to process startup parameters, a user can commencement your service with their own custom startup parameters in the service properties window. Even so, these startup parameters aren't persisted the next fourth dimension the service starts. To set startup parameters permanently, set them in the registry.

Each Windows service has a registry entry under the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services subkey. Under each service'due south subkey, use the Parameters subkey to shop information that your service can access. You tin can apply application configuration files for a Windows service the same fashion you do for other types of programs. For sample lawmaking, see ConfigurationManager.AppSettings.

To add startup parameters

  1. Select Program.cs, or MyNewService.Designer.vb, and so cull View Code from the shortcut menu. In the Main method, change the lawmaking to add an input parameter and pass it to the service constructor:

                      static void Main(string[] args) {     ServiceBase[] ServicesToRun;     ServicesToRun = new ServiceBase[]     {         new MyNewService(args)     };     ServiceBase.Run(ServicesToRun); }                                  
                      Shared Sub Main(ByVal cmdArgs() As String)     Dim ServicesToRun() As Organisation.ServiceProcess.ServiceBase = New System.ServiceProcess.ServiceBase() {New MyNewService(cmdArgs)}     System.ServiceProcess.ServiceBase.Run(ServicesToRun) Terminate Sub                                  
  2. In MyNewService.cs, or MyNewService.vb, change the MyNewService constructor to process the input parameter as follows:

                      using System.Diagnostics;  public MyNewService(string[] args) {     InitializeComponent();      string eventSourceName = "MySource";     cord logName = "MyNewLog";      if (args.Length > 0)     {        eventSourceName = args[0];     }      if (args.Length > ane)     {         logName = args[one];     }      eventLog1 = new EventLog();      if (!EventLog.SourceExists(eventSourceName))     {         EventLog.CreateEventSource(eventSourceName, logName);     }      eventLog1.Source = eventSourceName;     eventLog1.Log = logName; }                                  
                      Imports System.Diagnostics  Public Sub New(ByVal cmdArgs() Every bit Cord)     InitializeComponent()     Dim eventSourceName As Cord = "MySource"     Dim logName As String = "MyNewLog"     If (cmdArgs.Count() > 0) Then         eventSourceName = cmdArgs(0)     End If     If (cmdArgs.Count() > 1) Then         logName = cmdArgs(ane)     End If     eventLog1 = New EventLog()     If (Not EventLog.SourceExists(eventSourceName)) Then         EventLog.CreateEventSource(eventSourceName, logName)     Stop If     eventLog1.Source = eventSourceName     eventLog1.Log = logName End Sub                                  

    This code sets the result source and log name co-ordinate to the startup parameters that the user supplies. If no arguments are supplied, it uses default values.

  3. To specify the control-line arguments, add the following lawmaking to the ProjectInstaller form in ProjectInstaller.cs, or ProjectInstaller.vb:

                      protected override void OnBeforeInstall(IDictionary savedState) {     string parameter = "MySource1\" \"MyLogFile1";     Context.Parameters["assemblypath"] = "\"" + Context.Parameters["assemblypath"] + "\" \"" + parameter + "\"";     base.OnBeforeInstall(savedState); }                                  
                      Protected Overrides Sub OnBeforeInstall(ByVal savedState As IDictionary)     Dim parameter As String = "MySource1"" ""MyLogFile1"     Context.Parameters("assemblypath") = """" + Context.Parameters("assemblypath") + """ """ + parameter + """"     MyBase.OnBeforeInstall(savedState) End Sub                                  

    Typically, this value contains the full path to the executable for the Windows service. For the service to kickoff up correctly, the user must supply quotation marks for the path and each private parameter. A user tin can change the parameters in the ImagePath registry entry to change the startup parameters for the Windows service. Withal, a better way is to change the value programmatically and betrayal the functionality in a user-friendly manner, such as by using a direction or configuration utility.

Build the service

  1. In Solution Explorer, choose Backdrop from the shortcut carte for the MyNewService project.

    The belongings pages for your project appear.

  2. On the Application tab, in the Startup object list, choose MyNewService.Program, or Sub Main for Visual Basic projects.

  3. To build the project, in Solution Explorer, choose Build from the shortcut menu for your project (or press Ctrl+Shift+B).

Install the service

Now that you've built the Windows service, y'all tin install it. To install a Windows service, you must have administrator credentials on the figurer where information technology'southward installed.

  1. Open Developer Control Prompt for Visual Studio with administrative credentials.

  2. In Programmer Command Prompt for Visual Studio, navigate to the folder that contains your project'south output (by default, the \bin\Debug subdirectory of your project).

  3. Enter the following control:

                      installutil MyNewService.exe                                  

    If the service installs successfully, the command reports success.

    If the system can't observe installutil.exe, brand sure that it exists on your estimator. This tool is installed with the .NET Framework to the folder %windir%\Microsoft.NET\Framework[64]\<framework version>. For example, the default path for the 64-bit version is %windir%\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe.

    If the installutil.exe process fails, bank check the install log to find out why. Past default, the log is in the aforementioned binder as the service executable. The installation tin neglect if:

    • The RunInstallerAttribute grade isn't present on the ProjectInstaller class.
    • The attribute isn't set to truthful.
    • The ProjectInstaller course isn't defined as public.

For more than information, run into How to: Install and uninstall services.

Start and run the service

  1. In Windows, open the Services desktop app. Printing Windows+R to open up the Run box, enter services.msc, and so press Enter or select OK.

    You should see your service listed in Services, displayed alphabetically by the brandish name that you set for it.

    MyNewService in the Services window.

  2. To start the service, choose Start from the service's shortcut menu.

  3. To stop the service, cull Stop from the service'southward shortcut menu.

  4. (Optional) From the command line, use the commands net start <service name> and cyberspace stop <service name> to start and terminate your service.

Verify the event log output of your service

  1. In Windows, open the Event Viewer desktop app. Enter Event Viewer in the Windows search bar, and and then select Consequence Viewer from the search results.

    Tip

    In Visual Studio, you can admission event logs by opening Server Explorer from the View card (or press Ctrl+Alt+South) and expanding the Effect Logs node for the local computer.

  2. In Consequence Viewer, aggrandize Applications and Services Logs.

  3. Locate the listing for MyNewLog (or MyLogFile1 if you followed the procedure to add command-line arguments) and expand information technology. Y'all should see the entries for the ii actions (beginning and stop) that your service performed.

    Use the Event Viewer to see the event log entries

Clean up resources

If you no longer need the Windows service app, you can remove it.

  1. Open Developer Command Prompt for Visual Studio with administrative credentials.

  2. In the Developer Command Prompt for Visual Studio window, navigate to the binder that contains your project's output.

  3. Enter the post-obit control:

                      installutil.exe /u MyNewService.exe                                  

    If the service uninstalls successfully, the control reports that your service was successfully removed. For more information, run across How to: Install and uninstall services.

Next steps

Now that y'all've created the service, you can:

  • Create a standalone setup program for others to use to install your Windows service. Apply the WiX Toolset to create an installer for a Windows service. For other ideas, see Create an installer package.

  • Explore the ServiceController component, which enables you to send commands to the service y'all've installed.

  • Instead of creating the result log when the application runs, use an installer to create an issue log when you install the awarding. The consequence log is deleted by the installer when you lot uninstall the application. For more than information, see EventLogInstaller.

Run across also

  • Windows service applications
  • Introduction to Windows service applications
  • How to: Debug Windows service applications
  • Services (Windows)