Partager via


A Simple Windows Service Template for F#

Happy days! Carl Nolan is flying along with templates for F# programming - we now have a Simple Windows Service template up on Visual Studio gallery!

From Carls' blog:

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.