Tutorial: Create a Windows service app

This article demonstrates how to create a Windows service app in Visual Studio that writes messages to an effect 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 > Projection (or press Ctrl+Shift+N) to open the New Project window.

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

    Note

    If yous don't run into the Windows Service template, yous may need to install the .Cyberspace desktop development workload using Visual Studio Installer.

  3. For Name, enter MyNewService, so select OK.

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

    The project template includes a component class named Service1 that inherits from System.ServiceProcess.ServiceBase. Information technology includes much of the basic service lawmaking, such equally the lawmaking to first 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, then press Enter

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

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

    Rename prompt

  3. In the Blueprint tab, select Properties from the shortcut card. From the Properties window, change the ServiceName value to MyNewService.

    Service properties

  4. Select Relieve All from the File menu.

Add together features to the service

In this department, you add together a custom result log to the Windows service. The EventLog component is an instance of the type of component you tin can add to a Windows service.

Add together custom issue 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 [Pattern] tab.

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

  4. Define a custom event log.

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

                      public MyNewService() {     InitializeComponent();     eventLog1 = new System.Diagnostics.EventLog();     if (!System.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 proper noun driblet-downward listing.  Public Sub New()     MyBase.New()     InitializeComponent()     Me.EventLog1 = New Organization.Diagnostics.EventLog     If Not Organisation.Diagnostics.EventLog.SourceExists("MySource") Then         System.Diagnostics.EventLog.CreateEventSource("MySource",         "MyNewLog")     End If     EventLog1.Source = "MySource"     EventLog1.Log = "MyNewLog" Finish Sub                                  
  5. Add 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 Save All from the File menu.

Ascertain 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 together lawmaking that writes an entry to the outcome log when the service starts:

              protected override void OnStart(cord[] args) {     eventLog1.WriteEntry("In OnStart."); }                          
              ' To access the OnStart in Visual Basic, select OnStart from the ' method name drop-downwardly list.  Protected Overrides Sub OnStart(ByVal args() Every bit String)     EventLog1.WriteEntry("In OnStart") Terminate Sub                          

Polling

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

To gear up a simple polling machinery, use the System.Timers.Timer component. The timer raises an Elapsed event at regular intervals, at which time your service can do its monitoring. You use 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 System.Timers;                                  
                      Imports Organisation.Timers                                  
  2. Add the following code in the MyNewService.OnStart event to set up the polling machinery:

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

                      individual int eventId = ane;                                  
                      Private eventId As Integer = 1                                  
  4. In the MyNewService course, add the OnTimer method to handle the Timer.Elapsed upshot:

                      public void OnTimer(object sender, ElapsedEventArgs args) {     // TODO: Insert monitoring activities here.     eventLog1.WriteEntry("Monitoring the Organization", EventLogEntryType.Information, eventId++); }                                  
                      Private Sub OnTimer(sender As Object, e Equally Timers.ElapsedEventArgs)    ' TODO: Insert monitoring activities here.    eventLog1.WriteEntry("Monitoring the Organisation", EventLogEntryType.Information, eventId)    eventId = eventId + 1 End Sub                                  

Instead of running all your piece of work on the principal thread, y'all can run tasks by using background worker threads. For more than data, see Arrangement.ComponentModel.BackgroundWorker.

Define what occurs when the service is stopped

Insert a line of lawmaking 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 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 class:

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

Set service status

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

You can implement the SERVICE_START_PENDING and SERVICE_STOP_PENDING status settings past calculation code that calls the Windows SetServiceStatus function.

Implement service pending condition

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

                      using Organisation.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 yous'll apply 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 = i     SERVICE_START_PENDING = 2     SERVICE_STOP_PENDING = iii     SERVICE_RUNNING = iv     SERVICE_CONTINUE_PENDING = five     SERVICE_PAUSE_PENDING = 6     SERVICE_PAUSED = vii Terminate Enum  <StructLayout(LayoutKind.Sequential)> Public Structure ServiceStatus     Public dwServiceType As Long     Public dwCurrentState As ServiceState     Public dwControlsAccepted As Long     Public dwWin32ExitCode Equally Long     Public dwServiceSpecificExitCode Every bit Long     Public dwCheckPoint As Long     Public dwWaitHint As Long End Construction                                  

    Note

    The Service Control Director uses the dwWaitHint and dwCheckpoint members of the SERVICE_STATUS construction to decide how much time to wait for a Windows service to start or shut down. If your OnStart and OnStop methods run long, your service can request more time by calling SetServiceStatus once again with an incremented dwCheckPoint value.

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

                      [DllImport("advapi32.dll", SetLastError = truthful)] individual static extern bool SetServiceStatus(Organization.IntPtr handle, ref ServiceStatus serviceStatus);                                  
                      Declare Automobile Function SetServiceStatus Lib "advapi32.dll" (ByVal handle Every bit IntPtr, ByRef serviceStatus As ServiceStatus) As Boolean                                  
  4. To implement the SERVICE_START_PENDING condition, add the following code to the starting time 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 Every bit ServiceStatus = New ServiceStatus() serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING serviceStatus.dwWaitHint = 100000 SetServiceStatus(Me.ServiceHandle, serviceStatus)                                  
  5. Add together lawmaking to the end of the OnStart method to fix the status to SERVICE_RUNNING:

                      // Update the service state to Running. serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING; SetServiceStatus(this.ServiceHandle, ref serviceStatus);                                  
                      ' Update the service land 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 status and return the SERVICE_STOPPED status before the OnStop method exits.

    For example:

                      // Update the service state to Finish Awaiting. ServiceStatus serviceStatus = new ServiceStatus(); serviceStatus.dwCurrentState = ServiceState.SERVICE_STOP_PENDING; serviceStatus.dwWaitHint = 100000; SetServiceStatus(this.ServiceHandle, ref serviceStatus);  // Update the service land 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 state to Stopped. serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED SetServiceStatus(Me.ServiceHandle, serviceStatus)                                  

Add installers to the service

Before y'all run a Windows service, you need to install it, which registers it with the Service Command Managing director. Add together installers to your project 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, then choose Add Installer from the shortcut menu.

    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# project, or ServiceInstaller1 for a Visual Basic project, and so choose Properties from the shortcut card.

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

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

    This text appears in the Clarification 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 Name.

    This text appears in the Display Name column of the Services window. This name tin can be unlike from the ServiceName property, which is the name the arrangement uses (for instance, the name you apply for the net first command to start your service).

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

  8. When you're finished, the Backdrop windows should await similar the following figure:

    Installer Properties for a Windows service

  9. In the Design view for ProjectInstaller, cull serviceProcessInstaller1 for a Visual C# project, or ServiceProcessInstaller1 for a Visual Bones project, then choose Properties from the shortcut menu. Set the Account belongings to LocalSystem from the drop-downward list.

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

    Of import

    The LocalSystem account has broad permissions, including the ability to write to the effect log. Apply this business relationship with caution, because information technology might increase your risk of attacks from malicious software. For other tasks, consider using the LocalService account, which acts every bit a non-privileged user on the local computer and presents anonymous credentials to any remote server. This case fails if you lot effort to use the LocalService business relationship, considering it needs permission to write to the result log.

For more information well-nigh installers, see How to: Add installers to your service awarding.

(Optional) Ready startup parameters

Notation

Before you decide to add startup parameters, consider whether it'south the all-time mode to laissez passer information to your service. Although they're easy to apply and parse, and a user can easily override them, they might be harder for a user to discover and use without documentation. Mostly, if your service requires more than than just a few startup parameters, you should use the registry or a configuration file instead.

A Windows service can accept control-line arguments, or startup parameters. When yous add code to process startup parameters, a user can get-go your service with their own custom startup parameters in the service properties window. Nevertheless, these startup parameters aren't persisted the next time the service starts. To set startup parameters permanently, ready them in the registry.

Each Windows service has a registry entry under the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services subkey. Under each service'south subkey, use the Parameters subkey to shop data that your service can access. Y'all tin utilise application configuration files for a Windows service the same manner you practise for other types of programs. For sample code, see ConfigurationManager.AppSettings.

To add startup parameters

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

                      static void Primary(string[] args) {     ServiceBase[] ServicesToRun;     ServicesToRun = new ServiceBase[]     {         new MyNewService(args)     };     ServiceBase.Run(ServicesToRun); }                                  
                      Shared Sub Main(ByVal cmdArgs() As Cord)     Dim ServicesToRun() As System.ServiceProcess.ServiceBase = New System.ServiceProcess.ServiceBase() {New MyNewService(cmdArgs)}     System.ServiceProcess.ServiceBase.Run(ServicesToRun) End Sub                                  
  2. In MyNewService.cs, or MyNewService.vb, modify the MyNewService constructor to process the input parameter every bit follows:

                      using Organisation.Diagnostics;  public MyNewService(cord[] args) {     InitializeComponent();      string eventSourceName = "MySource";     string logName = "MyNewLog";      if (args.Length > 0)     {        eventSourceName = args[0];     }      if (args.Length > 1)     {         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 String)     InitializeComponent()     Dim eventSourceName As String = "MySource"     Dim logName As String = "MyNewLog"     If (cmdArgs.Count() > 0) Then         eventSourceName = cmdArgs(0)     End If     If (cmdArgs.Count() > i) Then         logName = cmdArgs(1)     Stop 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 code sets the event source and log proper noun according to the startup parameters that the user supplies. If no arguments are supplied, information technology uses default values.

  3. To specify the command-line arguments, add together 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 Equally Cord = "MySource1"" ""MyLogFile1"     Context.Parameters("assemblypath") = """" + Context.Parameters("assemblypath") + """ """ + parameter + """"     MyBase.OnBeforeInstall(savedState) Terminate Sub                                  

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

Build the service

  1. In Solution Explorer, choose Backdrop from the shortcut bill of fare for the MyNewService project.

    The belongings pages for your project announced.

  2. On the Awarding tab, in the Startup object listing, choose MyNewService.Program, or Sub Principal 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, yous tin can install it. To install a Windows service, you must have ambassador credentials on the computer where it'south installed.

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

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

  3. Enter the following control:

                      installutil MyNewService.exe                                  

    If the service installs successfully, the control reports success.

    If the system can't find installutil.exe, make sure that it exists on your computer. This tool is installed with the .NET Framework to the binder %windir%\Microsoft.Internet\Framework[64]\<framework version>. For example, the default path for the 64-chip 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 aforementioned folder as the service executable. The installation tin can fail if:

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

For more data, come across 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 then press Enter or select OK.

    You should see your service listed in Services, displayed alphabetically past the display proper noun that you prepare for it.

    MyNewService in the Services window.

  2. To outset the service, choose Get-go from the service'due south shortcut bill of fare.

  3. To stop the service, choose End from the service's shortcut menu.

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

Verify the outcome log output of your service

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

    Tip

    In Visual Studio, you can admission effect logs past opening Server Explorer from the View menu (or press Ctrl+Alt+S) and expanding the Event Logs node for the local computer.

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

  3. Locate the listing for MyNewLog (or MyLogFile1 if you lot followed the procedure to add command-line arguments) and expand it. You should meet the entries for the ii actions (start 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 can remove it.

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

  2. In the Developer Control Prompt for Visual Studio window, navigate to the binder that contains your project'south 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 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 plan for others to use to install your Windows service. Use the WiX Toolset to create an installer for a Windows service. For other ideas, see Create an installer parcel.

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

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

See also

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