Tutorial: Create a Windows service app

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

Create a service

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

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

  2. Detect and select the Windows Service (.NET Framework) projection template.

    Annotation

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

  3. For Name, enter MyNewService, and then select OK.

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

    The project template includes a component course named Service1 that inherits from System.ServiceProcess.ServiceBase. It includes much of the basic service code, such as the lawmaking to start the service.

Rename the service

Rename the service from Service1 to MyNewService.

  1. In Solution Explorer, select Service1.cs or Service1.vb, and cull Rename from the shortcut card. Rename the file to MyNewService.cs or MyNewService.vb, and so press Enter

    A pop-up window appears asking whether you would like to rename all references to the code element Service1.

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

    Rename prompt

  3. In the Pattern tab, select Properties from the shortcut menu. From the Properties window, alter the ServiceName value to MyNewService.

    Service properties

  4. Select Relieve 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 lot can add together to a Windows service.

Add custom outcome log functionality

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

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

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

  4. Define a custom effect log.

    For C#, edit the existing MyNewService() constructor as shown in the following lawmaking snippet. For Visual Bones, add the New() constructor every bit shown in the following code snippet.

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

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

Define what occurs when the service starts

In the lawmaking 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 result log when the service starts:

              protected override void OnStart(string[] args) {     eventLog1.WriteEntry("In OnStart."); }                          
              ' To admission the OnStart in Visual Basic, select OnStart from the ' method name driblet-down list.  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, information technology usually polls or monitors the system, which you set up in the OnStart method. The OnStart method must return to the operating organisation later on the service's functioning has begun and so that the organization isn't blocked.

To ready upwards a simple polling mechanism, utilise the Organisation.Timers.Timer component. The timer raises an Elapsed event at regular intervals, at which fourth dimension your service can do its monitoring. Yous utilize the Timer component as follows:

  • Set the properties of the Timer component in the MyNewService.OnStart method.
  • Start the timer past calling the Start method.
Set up the polling mechanism
  1. Add a using statement to MyNewService.cs, or an Imports statement to MyNewService.vb, for the System.Timers namespace:

                      using Organization.Timers;                                  
                      Imports System.Timers                                  
  2. Add the following lawmaking in the MyNewService.OnStart upshot to ready the polling mechanism:

                      // Set a timer that triggers every minute. Timer timer = new Timer(); timer.Interval = 60000; // lx seconds timer.Elapsed += new ElapsedEventHandler(this.OnTimer); timer.Start();                                  
                      ' Set up a timer that triggers every infinitesimal. Dim timer As Timer = New Timer() timer.Interval = 60000 ' 60 seconds AddHandler timer.Elapsed, AddressOf Me.OnTimer timer.Start()                                  
  3. In the MyNewService course, add a member variable. It contains the identifier of the next event to write into the event log:

                      individual int eventId = 1;                                  
                      Individual eventId As Integer = 1                                  
  4. In the MyNewService grade, add the OnTimer method to handle the Timer.Elapsed event:

                      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, e As Timers.ElapsedEventArgs)    ' TODO: Insert monitoring activities here.    eventLog1.WriteEntry("Monitoring the System", EventLogEntryType.Information, eventId)    eventId = eventId + ane Finish Sub                                  

Instead of running all your work on the main thread, you tin run tasks by using background worker threads. For more data, see Organisation.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                          

Define other deportment for the service

Y'all can override the OnPause, OnContinue, and OnShutdown methods to define boosted processing for your component.

The following lawmaking 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.") End Sub                          

Set up service status

Services report their status to the Service Control Director so that a user can tell whether a service is functioning correctly. By default, a service that inherits from ServiceBase reports a express ready of status settings, which include SERVICE_STOPPED, SERVICE_PAUSED, and SERVICE_RUNNING. If a service takes a while to starting time upwards, it's useful to report a SERVICE_START_PENDING status.

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

Implement service pending condition

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

                      using System.Runtime.InteropServices;                                  
                      Imports Organization.Runtime.InteropServices                                  
  2. Add the following code to MyNewService.cs, or MyNewService.vb, to declare the ServiceState values and to add together a structure for the status, which you'll use in a platform invoke phone 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 = 4     SERVICE_CONTINUE_PENDING = v     SERVICE_PAUSE_PENDING = half dozen     SERVICE_PAUSED = 7 Stop Enum  <StructLayout(LayoutKind.Sequential)> Public Construction ServiceStatus     Public dwServiceType As Long     Public dwCurrentState As ServiceState     Public dwControlsAccepted As Long     Public dwWin32ExitCode As Long     Public dwServiceSpecificExitCode Equally Long     Public dwCheckPoint As Long     Public dwWaitHint As Long End Structure                                  

    Note

    The Service Control Manager uses the dwWaitHint and dwCheckpoint members of the SERVICE_STATUS structure to determine how much time to expect for a Windows service to start or shut downwardly. If your OnStart and OnStop methods run long, your service can request more time by calling SetServiceStatus again with an incremented dwCheckPoint value.

  3. In the MyNewService grade, declare the SetServiceStatus function past using platform invoke:

                      [DllImport("advapi32.dll", SetLastError = true)] private static extern bool SetServiceStatus(System.IntPtr handle, ref ServiceStatus serviceStatus);                                  
                      Declare Motorcar Function SetServiceStatus Lib "advapi32.dll" (ByVal handle As IntPtr, ByRef serviceStatus As ServiceStatus) As Boolean                                  
  4. To implement the SERVICE_START_PENDING status, add the following lawmaking to the showtime of the OnStart method:

                      // Update the service state to Start Pending. ServiceStatus serviceStatus = new ServiceStatus(); serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING; serviceStatus.dwWaitHint = 100000; SetServiceStatus(this.ServiceHandle, ref serviceStatus);                                  
                      ' Update the service country to Start Awaiting. 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 land 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, echo this procedure in the OnStop method. Implement the SERVICE_STOP_PENDING condition and return the SERVICE_STOPPED status earlier the OnStop method exits.

    For example:

                      // Update the service land to Terminate 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 Stop Pending. Dim serviceStatus Equally 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, yous need to install information technology, which registers it with the Service Control Director. Add together installers to your projection to handle the registration details.

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

  2. In the Design view, select the groundwork area, and so cull Add Installer from the shortcut menu.

    Past default, Visual Studio adds a component grade named ProjectInstaller, which contains two installers, to your project. These installers are for your service and for the service'southward associated procedure.

  3. In the Design view for ProjectInstaller, select serviceInstaller1 for a Visual C# projection, or ServiceInstaller1 for a Visual Basic projection, so choose Properties from the shortcut bill of fare.

  4. In the Properties window, verify the ServiceName property is set to MyNewService.

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

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

    Service description in the Services window.

  6. Add text to the DisplayName belongings. For case, MyNewService Display Name.

    This text appears in the Display Proper noun column of the Services window. This name can be different from the ServiceName property, which is the name the system uses (for instance, the proper noun you employ for the net start command to beginning your service).

  7. Set the StartType belongings to Automatic from the drop-down listing.

  8. When y'all're finished, the Properties windows should wait like the following effigy:

    Installer Properties for a Windows service

  9. In the Design view for ProjectInstaller, choose 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-downwards list.

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

    Important

    The LocalSystem business relationship has broad permissions, including the ability to write to the upshot log. Use this account with caution, considering it might increase your run a risk of attacks from malicious software. For other tasks, consider using the LocalService business relationship, which acts as a non-privileged user on the local figurer and presents anonymous credentials to whatsoever remote server. This example fails if y'all endeavour to use the LocalService account, because information technology needs permission to write to the event log.

For more information nigh installers, run into How to: Add installers to your service awarding.

(Optional) Set startup parameters

Annotation

Before you make up one's mind to add startup parameters, consider whether it's the best way to pass information to your service. Although they're like shooting fish in a barrel to employ and parse, and a user can easily override them, they might exist harder for a user to discover and use without documentation. Generally, if your service requires more than just a few startup parameters, you should use the registry or a configuration file instead.

A Windows service can take command-line arguments, or startup parameters. When y'all add together code to process startup parameters, a user can first your service with their own custom startup parameters in the service backdrop window. However, 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's subkey, use the Parameters subkey to shop information that your service can admission. Y'all can use application configuration files for a Windows service the aforementioned way yous practise for other types of programs. For sample lawmaking, meet ConfigurationManager.AppSettings.

To add startup parameters

  1. Select Program.cs, or MyNewService.Designer.vb, then choose View Lawmaking from the shortcut menu. In the Primary method, change the code 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() Every bit Organisation.ServiceProcess.ServiceBase = New Organization.ServiceProcess.ServiceBase() {New MyNewService(cmdArgs)}     System.ServiceProcess.ServiceBase.Run(ServicesToRun) End Sub                                  
  2. In MyNewService.cs, or MyNewService.vb, change the MyNewService constructor to process the input parameter as follows:

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

    This lawmaking sets the consequence source and log name according to the startup parameters that the user supplies. If no arguments are supplied, it uses default values.

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

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

    Typically, this value contains the total path to the executable for the Windows service. For the service to start up correctly, the user must supply quotation marks for the path and each private parameter. A user can change the parameters in the ImagePath registry entry to change the startup parameters for the Windows service. However, a better way is to modify the value programmatically and expose the functionality in a user-friendly way, such equally by using a management or configuration utility.

Build the service

  1. In Solution Explorer, choose Properties from the shortcut menu for the MyNewService project.

    The belongings pages for your project appear.

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

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

Install the service

Now that you've built the Windows service, you tin install it. To install a Windows service, yous must have administrator credentials on the estimator where information technology's installed.

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

  2. In Developer Command Prompt for Visual Studio, navigate to the folder that contains your projection'southward output (past default, the \bin\Debug subdirectory of your project).

  3. Enter the following command:

                      installutil MyNewService.exe                                  

    If the service installs successfully, the command reports success.

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

    If the installutil.exe process fails, check the install log to find out why. By default, the log is in the same binder every bit the service executable. The installation tin can fail if:

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

For more information, see How to: Install and uninstall services.

Start and run the service

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

    Y'all should come across your service listed in Services, displayed alphabetically by the display name that you gear up for information technology.

    MyNewService in the Services window.

  2. To get-go the service, choose Outset from the service's shortcut menu.

  3. To finish the service, cull Stop from the service's shortcut carte.

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

Verify the event log output of your service

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

    Tip

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

  2. In Upshot Viewer, expand Applications and Services Logs.

  3. Locate the listing for MyNewLog (or MyLogFile1 if you followed the procedure to add command-line arguments) and expand it. You should see the entries for the 2 actions (beginning and stop) that your service performed.

    Use the Event Viewer to see the event log entries

Clean upwardly resources

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

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

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

  3. Enter the post-obit command:

                      installutil.exe /u MyNewService.exe                                  

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

Next steps

Now that you lot've created the service, you can:

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

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

  • Instead of creating the event log when the application runs, utilise an installer to create an event log when y'all install the awarding. The event log is deleted by the installer when you uninstall the application. For more information, come across EventLogInstaller.

Meet also

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