Partager via


F# Windows Application Template for Windows Service

Recently I created a posting outlining a project template for a WinForms application. This posting outlines a new project template that provides the elements for the creation windows service in F#. The template can be found on the Visual Studio Gallery:

https://visualstudiogallery.msdn.microsoft.com/1f2ee1da-e87f-4863-b98e-d8b7b63d2253

When the template is installed you get the following template added to your F# folder when creating a new F# project:

image

This template provides several projects elements:

  • A MyService.fs and Program.fs source file providing the service elements
  • An Installer.fs source file enabling the service to be installed using the installutil tool
  • A command file for installing and un-installing the service

The MyService.fs source file provides the implementation of the service. The template code provides the structure for the OnStart and OnStop methods and shows how an EventLog can be created and referenced:

namespace FSharp.Service

open System;
open System.Diagnostics;
open System.Linq;
open System.ServiceProcess;
open System.Text;

type public MyService() as service =
    inherit ServiceBase()
   
    // TODO define your service variables
    let eventLog = new EventLog();
    
    // TODO initialize your service
    let initService =
        service.ServiceName <- "FSharp.Service"

        // Define the Event Log
        let eventSource = "FSharp.Service"
        if not (EventLog.SourceExists(eventSource)) then
            EventLog.CreateEventSource(eventSource, "Application");

        eventLog.Source <- eventSource;
        eventLog.Log <- "Application";

    do
        initService

    // TODO define your service operations
    override service.OnStart(args:string[]) =
        base.OnStart(args)
        eventLog.WriteEntry("Service Started")

    override service.OnStop() =
        base.OnStop()
        eventLog.WriteEntry("Service Ended")

The entry point for the program is defined in the Program.fs source file:

namespace FSharp.Service

open System
open System.Collections.Generic
open System.Linq
open System.ServiceProcess
open System.Text

module Program =

    [<EntryPoint>]
    let Main(args) =
        // Define your services
        let myService = new MyService()

        // Start the services
        let servicesToRun = [| myService :> ServiceBase |]
        ServiceBase.Run(servicesToRun)

        // main entry point return
        0

As you can see for a service the entry point is defined using the [<EntryPoint>] attribute.

Finally, so that the installutil tool correctly installs the service, an Installer class is also defined:

namespace FSharp.Service

open System
open System.Configuration
open System.Configuration.Install
open System.ComponentModel
open System.Linq
open System.ServiceProcess

[<RunInstaller(true)>]
type public ProjectInstaller() as installer =
    inherit Installer()

    let processInstaller = new ServiceProcessInstaller();
    let serviceInstaller = new ServiceInstaller();

    // TODO initialize your service
    let initInstaller =

        // Define the process settings
        processInstaller.Account <- ServiceAccount.LocalSystem
        processInstaller.Password <- null
        processInstaller.Username <- null
        
        // Define the service settings
        serviceInstaller.Description <- "FSharp.Service MyService"
        serviceInstaller.ServiceName <- "FSharp.Service.MyService"
        serviceInstaller.StartType <- ServiceStartMode.Manual;
        
        // Define the installers
        let installers = [| processInstaller :> Installer; serviceInstaller :> Installer|]
        installer.Installers.AddRange(installers)

    do
        initInstaller

The template version installs the service using the Local System account. However, this can easily be changed.

Finally, the template creates a command file that can be used to install and un-install the service. When running this command file you will need a command prompt running with elevated privileges.

Once again, hopefully you will find this template useful.

Written by Carl Nolan