search
HomeBackend DevelopmentGolangWriting a Windows Service in Go

Writing a Windows Service in Go

Aug 28, 2024 am 06:40 AM

Writing a Windows Service in Go

Table Of Contents

  • Introduction
  • What exactly is a windows "service"?
  • Why Golang?
  • Writing a windows service in Go
  • Installing and Starting the Service
  • Conclusion
  • Complete Code

Introduction

Hello Devs, It's been a while since I wrote something windows-ish. So, today I want to guide you guys on how to write a Windows Service Application in Go. Yes, you heard it right, it's go language. In this tutorial blog, we'll cover some basic stuffs about Windows Service Applications and at the later part, I'll guide you through a simple code walk through where we write code for a Windows service which logs some information to a file. Without further ado, Let's get started...!

What exactly is a windows "service"?

A Windows Service Application a.k.a. Windows Services are tiny applications that runs in background. Unlike normal windows applications, they don't have a GUI or any forms of user interface. These service applications starts to run when the computer boots up. It runs irrespective of which user account it's running in. It's lifecycle (start, stop, pause, continue etc.,) are controlled by a program called Service Control Manager (SCM).

So, from this we can understand that we should write our Windows Service in such a way that the SCM should interact with our Windows Service and manage it's lifecycle.

Why Golang?

There are several factors where you may consider Go for writing Windows Services.

Concurrency

Go's concurrency model allows for faster and resource efficient processing. Go's goroutines allows us to write applications which can do multi-tasking without any blocking or deadlocking.

Simplicity

Traditionally, Windows Services are written using either C++ or C (sometimes C#) which not only results in a complex code, but also poor DX (Developer Experience). Go's implementation of Windows Services is straightforward and every line of code makes sense.

Static Binaries

You may ask, "Why not use even more simple language like python?". The reason is due to the interpreted nature of Python. Go compiles to a statically linked single file binary which is essential for a Windows Service to function efficiently. Go binaries doesn't require any runtime / interpreter. Go code can also be cross compiled.

Low Level Access

Though being a Garbage Collected language, Go provides solid support to interact with low level elements. We can easily invoke win32 APIs and general syscalls in go.

Alright, enough information. Let's code...

Writing a windows service in Go

This code walk-through assumes that you have a basic knowledge on Go syntax. If not, A Tour of Go would be a nice place to learn it.

  • Firstly, let's name our project. I'll name mines as cosmic/my_service. Create a go.mod file,
PS C:\> go mod init cosmic/my_service
  • Now we need to install golang.org/x/sys package. This package provides go language support for Windows OS related applications.
PS C:\> go get golang.org/x/sys

Note: This package also contains OS level go language support for UNIX based OS'es like Mac OS and Linux.

  • Create a main.go file. The main.go file contains main function, which acts as a entry-point for our Go application/service.

  • For creating a service instance, we need to write something called Service Context, which implements Handler interface from golang.org/x/sys/windows/svc.

So, the interface definition looks something like this

type Handler interface {
    Execute(args []string, r 



<p>Execute function will be called by the package code at the start of the service, and the service will exit once the Execute completes. </p>

<p>We read service change requests from receive-only channel r and act accordingly. We should also keep our service updated with sending signals to send-only channel s. We can pass optional arguments to args parameter.</p>

<p>On exiting, we can return with the exitCode being 0 on a successful execution. We can also use svcSpecificEC for that.</p>

  • Now, create a type named myService which will act as our Service Context.
type myService struct{}
  • After creating the type myService, add the above mentioned Execute as a method to it so that it implements Handler interface.
func (m *myService) Execute(args []string, r 



  • Now that we have successfully implemented the Handler interface, we can now start writing the actual logic.

Create a constant, with the signals that our service can accept from SCM.

const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown | svc.AcceptPauseAndContinue

Our main goal is the log some data every 30 seconds. So we need to define a thread safe timer for that.

tick := time.Tick(30 * time.Second)

So, we have done all the initialization stuffs. It's time to send START signal to the SCM. we're going to do exactly that,

status 



<p>Now we're going to write a loop which acts as a <em>mainloop</em> for our application. Handling events in loop makes our application never ending and we can break the loop only when the SCM sends STOP or SHUTDOWN signal.<br>
</p>

<pre class="brush:php;toolbar:false">loop:
    for {
        select {
        case 



<p>Here we used a select statement to receive signals from channels. In first case, we handle the Timer's tick signal. This case receives signal every 30 seconds, as we declared before. We log a string "Tick Handled...!" in this case.</p>

<p>Secondly, we handle the signals from SCM via the receive-only r channel. So, we assign the value of the signal from r to a variable c and using a switch statement, we can handle all the lifecycle event/signals of our service. We can see about each lifecycle below,</p>

<ol>
<li>
svc.Interrogate - Signal requested by SCM on a timely fashion to check the current status of the service.</li>
<li>
svc.Stop and svc.Shutdown - Signal sent by SCM when our service needs to be stopped or Shut Down.</li>
<li>
svc.Pause - Signal sent by SCM to pause the service execution without shutting it down.</li>
<li>
svc.Continue - Signal sent by SCM to resume the paused execution state of the service.</li>
</ol>

<p>So, when on receiving either svc.Stop or svc.Shutdown signal, we break the loop. It is to be noted that we need to send STOP signal to the SCM to let the SCM know that our service is stopping.<br>
</p>

<pre class="brush:php;toolbar:false">status 



  • Now we write a function called runService where we enable our service to run either in Debug mode or in Service Control Mode.

Note: It's super hard to debug Windows Service Applications when running on Service Control Mode. That's why we are writing an additional Debug mode.

func runService(name string, isDebug bool) {
    if isDebug {
        err := debug.Run(name, &myService{})
        if err != nil {
            log.Fatalln("Error running service in debug mode.")
        }
    } else {
        err := svc.Run(name, &myService{})
        if err != nil {
            log.Fatalln("Error running service in debug mode.")
        }
    }
}
  • Finally we can call the runService function in our main function.
func main() {

    f, err := os.OpenFile("debug.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    if err != nil {
        log.Fatalln(fmt.Errorf("error opening file: %v", err))
    }
    defer f.Close()

    log.SetOutput(f)
    runService("myservice", false) //change to true to run in debug mode
}

Note: We are logging the logs to a log file. In advanced scenarios, we log our logs to Windows Event Logger. (phew, that sounds like a tongue twister ?)

  • Now run go build to create a binary '.exe'. Optionally, we can optimize and reduce the binary file size by using the following command,
PS C:\> go build -ldflags "-s -w"

Installing and Starting the Service

For installing, deleting, starting and stopping our service, we use an inbuilt tool called sc.exe

To install our service, run the following command in powershell as Administrator,

PS C:\> sc.exe create MyService <path to your service_app.exe>
</path>

To start our service, run the following command,

PS C:\> sc.exe start MyService

To delete our service, run the following command,

PS C:\> sc.exe delete MyService

You can explore more commands, just type sc.exe without any arguments to see the available commands.

Conclusion

As we can see, implementing Windows Services in go is straightforward and requires minimal implementation. You can write your own windows services which acts as a web server and more. Thanks for reading and don't forget to drop a ❤️.

Complete Code

Here is the complete code for your reference.

// file: main.go

package main

import (
    "fmt"
    "golang.org/x/sys/windows/svc"
    "golang.org/x/sys/windows/svc/debug"
    "log"
    "os"
    "time"
)

type myService struct{}

func (m *myService) Execute(args []string, r 




          

            
        

The above is the detailed content of Writing a Windows Service in Go. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
String Manipulation in Go: Mastering the 'strings' PackageString Manipulation in Go: Mastering the 'strings' PackageMay 14, 2025 am 12:19 AM

Mastering the strings package in Go language can improve text processing capabilities and development efficiency. 1) Use the Contains function to check substrings, 2) Use the Index function to find the substring position, 3) Join function efficiently splice string slices, 4) Replace function to replace substrings. Be careful to avoid common errors, such as not checking for empty strings and large string operation performance issues.

Go 'strings' package tips and tricksGo 'strings' package tips and tricksMay 14, 2025 am 12:18 AM

You should care about the strings package in Go because it simplifies string manipulation and makes the code clearer and more efficient. 1) Use strings.Join to efficiently splice strings; 2) Use strings.Fields to divide strings by blank characters; 3) Find substring positions through strings.Index and strings.LastIndex; 4) Use strings.ReplaceAll to replace strings; 5) Use strings.Builder to efficiently splice strings; 6) Always verify input to avoid unexpected results.

'strings' Package in Go: Your Go-To for String Operations'strings' Package in Go: Your Go-To for String OperationsMay 14, 2025 am 12:17 AM

ThestringspackageinGoisessentialforefficientstringmanipulation.1)Itofferssimpleyetpowerfulfunctionsfortaskslikecheckingsubstringsandjoiningstrings.2)IthandlesUnicodewell,withfunctionslikestrings.Fieldsforwhitespace-separatedvalues.3)Forperformance,st

Go bytes package vs strings package: Which should I use?Go bytes package vs strings package: Which should I use?May 14, 2025 am 12:12 AM

WhendecidingbetweenGo'sbytespackageandstringspackage,usebytes.Bufferforbinarydataandstrings.Builderforstringoperations.1)Usebytes.Bufferforworkingwithbyteslices,binarydata,appendingdifferentdatatypes,andwritingtoio.Writer.2)Usestrings.Builderforstrin

How to use the 'strings' package to manipulate strings in Go step by stepHow to use the 'strings' package to manipulate strings in Go step by stepMay 13, 2025 am 12:12 AM

Go's strings package provides a variety of string manipulation functions. 1) Use strings.Contains to check substrings. 2) Use strings.Split to split the string into substring slices. 3) Merge strings through strings.Join. 4) Use strings.TrimSpace or strings.Trim to remove blanks or specified characters at the beginning and end of a string. 5) Replace all specified substrings with strings.ReplaceAll. 6) Use strings.HasPrefix or strings.HasSuffix to check the prefix or suffix of the string.

Go strings package: how to improve my code?Go strings package: how to improve my code?May 13, 2025 am 12:10 AM

Using the Go language strings package can improve code quality. 1) Use strings.Join() to elegantly connect string arrays to avoid performance overhead. 2) Combine strings.Split() and strings.Contains() to process text and pay attention to case sensitivity issues. 3) Avoid abuse of strings.Replace() and consider using regular expressions for a large number of substitutions. 4) Use strings.Builder to improve the performance of frequently splicing strings.

What are the most useful functions in the GO bytes package?What are the most useful functions in the GO bytes package?May 13, 2025 am 12:09 AM

Go's bytes package provides a variety of practical functions to handle byte slicing. 1.bytes.Contains is used to check whether the byte slice contains a specific sequence. 2.bytes.Split is used to split byte slices into smallerpieces. 3.bytes.Join is used to concatenate multiple byte slices into one. 4.bytes.TrimSpace is used to remove the front and back blanks of byte slices. 5.bytes.Equal is used to compare whether two byte slices are equal. 6.bytes.Index is used to find the starting index of sub-slices in largerslices.

Mastering Binary Data Handling with Go's 'encoding/binary' Package: A Comprehensive GuideMastering Binary Data Handling with Go's 'encoding/binary' Package: A Comprehensive GuideMay 13, 2025 am 12:07 AM

Theencoding/binarypackageinGoisessentialbecauseitprovidesastandardizedwaytoreadandwritebinarydata,ensuringcross-platformcompatibilityandhandlingdifferentendianness.ItoffersfunctionslikeRead,Write,ReadUvarint,andWriteUvarintforprecisecontroloverbinary

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

SublimeText3 Linux new version

SublimeText3 Linux new version

SublimeText3 Linux latest version

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

VSCode Windows 64-bit Download

VSCode Windows 64-bit Download

A free and powerful IDE editor launched by Microsoft

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)