Tutorial: Create a Windows service app

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

Create a service

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

  1. From the Visual Studio File carte, select New > Projection (or printing Ctrl+Shift+North) to open up the New Project window.

  2. Find and select the Windows Service (.Cyberspace Framework) project 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 and then select OK.

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

    The project template includes a component class named Service1 that inherits from System.ServiceProcess.ServiceBase. It includes much of the basic service code, such equally 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 choose Rename from the shortcut menu. Rename the file to MyNewService.cs or MyNewService.vb, and then press Enter

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

  2. In the pop-upwards window, select Yep.

    Rename prompt

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

    Service properties

  4. Select Save All from the File bill of fare.

Add features to the service

In this section, you add together a custom upshot log to the Windows service. The EventLog component is an example of the type of component you can add to a Windows service.

Add custom event log functionality

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

  2. In Toolbox, aggrandize Components, and then 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. Define a custom event log.

    For C#, edit the existing MyNewService() constructor equally shown in the following code snippet. For Visual Basic, add the New() constructor as shown in the following code snippet.

                      public MyNewService() {     InitializeComponent();     eventLog1 = new System.Diagnostics.EventLog();     if (!Organisation.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 driblet-down listing.  Public Sub New()     MyBase.New()     InitializeComponent()     Me.EventLog1 = New System.Diagnostics.EventLog     If Non System.Diagnostics.EventLog.SourceExists("MySource") So         System.Diagnostics.EventLog.CreateEventSource("MySource",         "MyNewLog")     End If     EventLog1.Source = "MySource"     EventLog1.Log = "MyNewLog" End Sub                                  
  5. Add together a using statement to MyNewService.cs (if it doesn't already be), or an Imports argument to MyNewService.vb, for the System.Diagnostics namespace:

                      using Organization.Diagnostics;                                  
                      Imports Organization.Diagnostics                                  
  6. Select Save 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 event log when the service starts:

              protected override void OnStart(cord[] 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() Every bit String)     EventLog1.WriteEntry("In OnStart") End Sub                          

Polling

Because a service application is designed to exist long-running, it commonly polls or monitors the system, which you set in the OnStart method. The OnStart method must return to the operating organisation after the service's operation has begun and so that the organization isn't blocked.

To set a simple polling machinery, apply 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 use the Timer component as follows:

  • Ready the backdrop of the Timer component in the MyNewService.OnStart method.
  • Kickoff the timer past calling the Commencement method.
Prepare the polling machinery
  1. Add a using statement to MyNewService.cs, or an Imports statement to MyNewService.vb, for the System.Timers namespace:

                      using System.Timers;                                  
                      Imports Arrangement.Timers                                  
  2. Add together the following code in the MyNewService.OnStart event to set up the polling mechanism:

                      // Gear up up a timer that triggers every minute. Timer timer = new Timer(); timer.Interval = 60000; // 60 seconds timer.Elapsed += new ElapsedEventHandler(this.OnTimer); timer.Offset();                                  
                      ' Ready a timer that triggers every minute. Dim timer Equally Timer = New Timer() timer.Interval = 60000 ' 60 seconds AddHandler timer.Elapsed, AddressOf Me.OnTimer timer.Get-go()                                  
  3. In the MyNewService class, add together a member variable. It contains the identifier of the next event to write into the event log:

                      private int eventId = i;                                  
                      Private eventId As Integer = 1                                  
  4. In the MyNewService class, 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.Information, eventId++); }                                  
                      Private Sub OnTimer(sender As Object, due east As Timers.ElapsedEventArgs)    ' TODO: Insert monitoring activities here.    eventLog1.WriteEntry("Monitoring the Arrangement", EventLogEntryType.Information, eventId)    eventId = eventId + 1 End Sub                                  

Instead of running all your work on the main thread, y'all can run tasks past using background worker threads. For more information, run into 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 effect log when the service is stopped:

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

Define other deportment for the service

Yous can override the OnPause, OnContinue, and OnShutdown methods to define additional 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.") End Sub                          

Prepare service status

Services report their status to the Service Control Director and then that a user can tell whether a service is functioning correctly. Past default, a service that inherits from ServiceBase reports a express fix of condition settings, which include SERVICE_STOPPED, SERVICE_PAUSED, and SERVICE_RUNNING. If a service takes a while to start upwardly, it's useful to study a SERVICE_START_PENDING status.

Y'all can implement the SERVICE_START_PENDING and SERVICE_STOP_PENDING status settings by adding code that calls the Windows SetServiceStatus role.

Implement service awaiting status

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

                      using System.Runtime.InteropServices;                                  
                      Imports Organisation.Runtime.InteropServices                                  
  2. Add together 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 utilise 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 = one     SERVICE_START_PENDING = 2     SERVICE_STOP_PENDING = 3     SERVICE_RUNNING = 4     SERVICE_CONTINUE_PENDING = 5     SERVICE_PAUSE_PENDING = 6     SERVICE_PAUSED = seven Cease Enum  <StructLayout(LayoutKind.Sequential)> Public Structure ServiceStatus     Public dwServiceType Equally Long     Public dwCurrentState As ServiceState     Public dwControlsAccepted As Long     Public dwWin32ExitCode As Long     Public dwServiceSpecificExitCode As Long     Public dwCheckPoint Equally Long     Public dwWaitHint As Long End Structure                                  

    Note

    The Service Command Manager uses the dwWaitHint and dwCheckpoint members of the SERVICE_STATUS structure to determine how much fourth dimension to wait for a Windows service to commencement or shut down. If your OnStart and OnStop methods run long, your service can request more than time past calling SetServiceStatus once more with an incremented dwCheckPoint value.

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

                      [DllImport("advapi32.dll", SetLastError = true)] individual static extern bool SetServiceStatus(System.IntPtr handle, ref ServiceStatus serviceStatus);                                  
                      Declare Auto Role SetServiceStatus Lib "advapi32.dll" (ByVal handle Every bit IntPtr, ByRef serviceStatus Every bit ServiceStatus) As Boolean                                  
  4. To implement the SERVICE_START_PENDING status, add the following code to the beginning 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 state to Start 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 gear up the status to SERVICE_RUNNING:

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

    For example:

                      // Update the service state to Stop 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 land to Stop Pending. Dim serviceStatus As ServiceStatus = New ServiceStatus() serviceStatus.dwCurrentState = ServiceState.SERVICE_STOP_PENDING serviceStatus.dwWaitHint = 100000 SetServiceStatus(Me.ServiceHandle, serviceStatus)  ' Update the service state to Stopped. serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED SetServiceStatus(Me.ServiceHandle, serviceStatus)                                  

Add together installers to the service

Before you run a Windows service, yous need to install it, which registers it with the Service Control Managing director. Add installers to your project to handle the registration details.

  1. In Solution Explorer, from the shortcut carte 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 card.

    By default, Visual Studio adds a component class named ProjectInstaller, which contains two installers, to your project. 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# projection, or ServiceInstaller1 for a Visual Basic project, and then choose Properties from the shortcut carte du jour.

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

  5. Add together text to the Clarification holding, such as A sample service.

    This text appears in the Description column 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 example, MyNewService Display Proper name.

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

  7. Set the StartType property to Automatic from the drop-down list.

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

    Installer Properties for a Windows service

  9. In the Pattern view for ProjectInstaller, choose serviceProcessInstaller1 for a Visual C# project, or ServiceProcessInstaller1 for a Visual Bones project, then cull Properties from the shortcut carte. Set the Business relationship property to LocalSystem from the driblet-downward 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 consequence log. Use this account with caution, considering 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 estimator and presents bearding credentials to any remote server. This example fails if you try to employ the LocalService account, because information technology needs permission to write to the outcome log.

For more information well-nigh installers, run into How to: Add together installers to your service application.

(Optional) Gear up startup parameters

Note

Earlier yous make up one's mind to add startup parameters, consider whether it's the best mode to pass information to your service. Although they're easy to employ and parse, and a user tin easily override them, they might be harder for a user to discover and utilize 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 tin can accept command-line arguments, or startup parameters. When you add code to procedure startup parameters, a user can starting time 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 nether the HKEY_LOCAL_MACHINE\Arrangement\CurrentControlSet\Services subkey. Under each service'southward subkey, use the Parameters subkey to store information that your service tin can access. You can use awarding configuration files for a Windows service the same style you practice for other types of programs. For sample code, see ConfigurationManager.AppSettings.

To add startup parameters

  1. Select Program.cs, or MyNewService.Designer.vb, then cull View Lawmaking from the shortcut menu. In the Main 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 Master(ByVal cmdArgs() As String)     Dim ServicesToRun() Equally Organization.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 System.Diagnostics;  public MyNewService(string[] args) {     InitializeComponent();      string eventSourceName = "MySource";     cord logName = "MyNewLog";      if (args.Length > 0)     {        eventSourceName = args[0];     }      if (args.Length > 1)     {         logName = args[1];     }      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() As Cord)     InitializeComponent()     Dim eventSourceName As String = "MySource"     Dim logName Every bit String = "MyNewLog"     If (cmdArgs.Count() > 0) And then         eventSourceName = cmdArgs(0)     Cease If     If (cmdArgs.Count() > 1) And then         logName = cmdArgs(1)     End If     eventLog1 = New EventLog()     If (Non EventLog.SourceExists(eventSourceName)) So         EventLog.CreateEventSource(eventSourceName, logName)     Stop If     eventLog1.Source = eventSourceName     eventLog1.Log = logName End Sub                                  

    This code sets the event source and log proper name according 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 post-obit code to the ProjectInstaller class in ProjectInstaller.cs, or ProjectInstaller.vb:

                      protected override void OnBeforeInstall(IDictionary savedState) {     string parameter = "MySource1\" \"MyLogFile1";     Context.Parameters["assemblypath"] = "\"" + Context.Parameters["assemblypath"] + "\" \"" + parameter + "\"";     base of operations.OnBeforeInstall(savedState); }                                  
                      Protected Overrides Sub OnBeforeInstall(ByVal savedState As IDictionary)     Dim parameter Every bit 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 offset up correctly, the user must supply quotation marks for the path and each individual parameter. A user tin alter the parameters in the ImagePath registry entry to change the startup parameters for the Windows service. However, a ameliorate way is to change the value programmatically and expose the functionality in a user-friendly manner, such every bit by using a direction 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 projection appear.

  2. On the Awarding tab, in the Startup object list, cull MyNewService.Program, or Sub Main for Visual Bones projects.

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

Install the service

At present that you've built the Windows service, you can install it. To install a Windows service, you must have administrator credentials on the computer where information technology's installed.

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

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

  3. Enter the post-obit control:

                      installutil MyNewService.exe                                  

    If the service installs successfully, the command reports success.

    If the system can't detect installutil.exe, make sure that it exists on your reckoner. This tool is installed with the .Internet 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 procedure fails, cheque the install log to detect out why. By default, the log is in the same folder as the service executable. The installation tin fail if:

    • The RunInstallerAttribute class isn't present on the ProjectInstaller class.
    • The attribute isn't set to true.
    • The ProjectInstaller class isn't defined every bit public.

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

Outset 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 printing Enter or select OK.

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

    MyNewService in the Services window.

  2. To start the service, cull Start from the service'southward shortcut menu.

  3. To stop the service, choose Stop from the service's shortcut carte du jour.

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

Verify the event log output of your service

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

    Tip

    In Visual Studio, yous tin access event logs by opening Server Explorer from the View card (or printing Ctrl+Alt+S) and expanding the Event Logs node for the local computer.

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

  3. Locate the listing for MyNewLog (or MyLogFile1 if y'all followed the procedure to add command-line arguments) and expand it. You should run across the entries for the ii actions (showtime and stop) that your service performed.

    Use the Event Viewer to see the event log entries

Make clean up resources

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

  1. Open up Developer Control 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'due south output.

  3. Enter the post-obit command:

                      installutil.exe /u MyNewService.exe                                  

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

Side by side steps

At present that you've created the service, you can:

  • Create a standalone setup programme for others to utilize to install your Windows service. Utilize 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 yous to send commands to the service you lot've installed.

  • Instead of creating the event log when the application runs, utilize an installer to create an event log when you install the application. The consequence log is deleted past the installer when yous uninstall the awarding. For more information, see EventLogInstaller.

See besides

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