The Windows Services package is Windows-only and uses the Windows Service Control Manager API.
Introduction
The winservices package provides functionality to query and monitor Windows services. It wraps the Windows Service Control Manager (SCM) API through Go’s golang.org/x/sys/windows package.
Installation
go get github.com/shirou/gopsutil/v4/winservices
Key Features
Service Information Query service configuration including start type, executable path, and dependencies
Service Status Get current service state, PID, and accepted control commands
List Services Enumerate all Windows services on the system
Process Information Get the process ID of running services for monitoring
Service Type
The main data structure representing a Windows service.
type Service struct {
Name string
Config mgr . Config
Status ServiceStatus
srv * mgr . Service
}
Fields
Name - Service name
Config - Service configuration (from mgr.Config)
Status - Current service status
srv - Internal service handle (private)
ServiceStatus Type
Combines service state with process information.
type ServiceStatus struct {
State svc . State // Current service state
Accepts svc . Accepted // Accepted control commands
Pid uint32 // Process ID (if running)
Win32ExitCode uint32 // Last exit code
}
State Values
The State field uses svc.State type:
svc.Stopped - Service is stopped
svc.StartPending - Service is starting
svc.StopPending - Service is stopping
svc.Running - Service is running
svc.ContinuePending - Service continue is pending
svc.PausePending - Service pause is pending
svc.Paused - Service is paused
Accepts Values
The Accepts field indicates which control commands the service accepts:
svc.AcceptStop - Can be stopped
svc.AcceptPauseAndContinue - Can be paused/continued
svc.AcceptShutdown - Can handle system shutdown
svc.AcceptParamChange - Can handle parameter changes
svc.AcceptNetBindChange - Can handle network binding changes
Core Functions
NewService
Creates a new Service instance for the specified service name.
func NewService ( name string ) ( * Service , error )
Example
import (
" fmt "
" log "
" github.com/shirou/gopsutil/v4/winservices "
)
func main () {
service , err := winservices . NewService ( "wuauserv" ) // Windows Update service
if err != nil {
log . Fatal ( err )
}
fmt . Printf ( "Service: %s \n " , service . Name )
}
Creating a service requires opening a handle to the Service Control Manager. Ensure your application has appropriate permissions.
GetServiceDetail
Retrieves complete service information including configuration and status.
func ( s * Service ) GetServiceDetail () error
func ( s * Service ) GetServiceDetailWithContext ( ctx context . Context ) error
This populates both Config and Status fields of the Service struct.
Example
import (
" fmt "
" log "
" github.com/shirou/gopsutil/v4/winservices "
" golang.org/x/sys/windows/svc "
)
func main () {
service , err := winservices . NewService ( "wuauserv" )
if err != nil {
log . Fatal ( err )
}
// Populate config and status
err = service . GetServiceDetail ()
if err != nil {
log . Fatal ( err )
}
// Access configuration
fmt . Printf ( "Display Name: %s \n " , service . Config . DisplayName )
fmt . Printf ( "Description: %s \n " , service . Config . Description )
fmt . Printf ( "Binary Path: %s \n " , service . Config . BinaryPathName )
// Access status
fmt . Printf ( "State: %v \n " , service . Status . State )
if service . Status . State == svc . Running {
fmt . Printf ( "PID: %d \n " , service . Status . Pid )
}
}
QueryServiceConfig
Retrieves only the service configuration.
func ( s * Service ) QueryServiceConfig () ( mgr . Config , error )
func ( s * Service ) QueryServiceConfigWithContext ( ctx context . Context ) ( mgr . Config , error )
mgr.Config Structure
Returns mgr.Config from golang.org/x/sys/windows/svc/mgr:
type Config struct {
ServiceType uint32
StartType uint32
ErrorControl uint32
BinaryPathName string // Path to service executable
LoadOrderGroup string
TagId uint32
Dependencies [] string // Service dependencies
ServiceStartName string // Account name
DisplayName string // Friendly name
Password string
Description string
}
Example
service , err := winservices . NewService ( "wuauserv" )
if err != nil {
log . Fatal ( err )
}
config , err := service . QueryServiceConfig ()
if err != nil {
log . Fatal ( err )
}
fmt . Printf ( "Service: %s \n " , config . DisplayName )
fmt . Printf ( "Executable: %s \n " , config . BinaryPathName )
fmt . Printf ( "Start Type: %d \n " , config . StartType )
if len ( config . Dependencies ) > 0 {
fmt . Println ( "Dependencies:" )
for _ , dep := range config . Dependencies {
fmt . Printf ( " - %s \n " , dep )
}
}
QueryStatus
Retrieves only the current service status.
func ( s * Service ) QueryStatus () ( ServiceStatus , error )
func ( s * Service ) QueryStatusWithContext ( ctx context . Context ) ( ServiceStatus , error )
Example
import (
" fmt "
" log "
" golang.org/x/sys/windows/svc "
" github.com/shirou/gopsutil/v4/winservices "
)
service , err := winservices . NewService ( "wuauserv" )
if err != nil {
log . Fatal ( err )
}
status , err := service . QueryStatus ()
if err != nil {
log . Fatal ( err )
}
fmt . Printf ( "State: %v \n " , status . State )
fmt . Printf ( "PID: %d \n " , status . Pid )
fmt . Printf ( "Exit Code: %d \n " , status . Win32ExitCode )
if status . Accepts & svc . AcceptStop != 0 {
fmt . Println ( "Service can be stopped" )
}
if status . Accepts & svc . AcceptPauseAndContinue != 0 {
fmt . Println ( "Service can be paused/continued" )
}
ListServices
Enumerates all Windows services on the system.
func ListServices () ([] Service , error )
This function returns services with only the Name field populated. Call GetServiceDetail() on each service to retrieve full information.
Example: List All Services
import (
" fmt "
" log "
" github.com/shirou/gopsutil/v4/winservices "
)
func main () {
services , err := winservices . ListServices ()
if err != nil {
log . Fatal ( err )
}
fmt . Printf ( "Found %d services \n\n " , len ( services ))
for _ , svc := range services {
fmt . Printf ( "- %s \n " , svc . Name )
}
}
Example: List Running Services
import (
" fmt "
" log "
" golang.org/x/sys/windows/svc "
" github.com/shirou/gopsutil/v4/winservices "
)
func main () {
services , err := winservices . ListServices ()
if err != nil {
log . Fatal ( err )
}
fmt . Println ( "Running services: \n " )
for _ , service := range services {
// Query status for each service
s , err := winservices . NewService ( service . Name )
if err != nil {
continue
}
status , err := s . QueryStatus ()
if err != nil {
continue
}
if status . State == svc . Running {
config , _ := s . QueryServiceConfig ()
fmt . Printf ( " %-30s PID: %-6d %s \n " ,
service . Name ,
status . Pid ,
config . DisplayName ,
)
}
}
}
Complete Example: Service Monitor
package main
import (
" fmt "
" log "
" time "
" golang.org/x/sys/windows/svc "
" github.com/shirou/gopsutil/v4/winservices "
)
func monitorService ( serviceName string ) {
service , err := winservices . NewService ( serviceName )
if err != nil {
log . Fatal ( err )
}
ticker := time . NewTicker ( 5 * time . Second )
defer ticker . Stop ()
fmt . Printf ( "Monitoring service: %s \n\n " , serviceName )
for range ticker . C {
status , err := service . QueryStatus ()
if err != nil {
log . Printf ( "Error: %v " , err )
continue
}
timestamp := time . Now (). Format ( "15:04:05" )
stateStr := stateToString ( status . State )
if status . State == svc . Running {
fmt . Printf ( "[ %s ] %s (PID: %d ) \n " , timestamp , stateStr , status . Pid )
} else {
fmt . Printf ( "[ %s ] %s \n " , timestamp , stateStr )
}
}
}
func stateToString ( state svc . State ) string {
switch state {
case svc . Stopped :
return "STOPPED"
case svc . StartPending :
return "STARTING"
case svc . StopPending :
return "STOPPING"
case svc . Running :
return "RUNNING"
case svc . ContinuePending :
return "CONTINUE PENDING"
case svc . PausePending :
return "PAUSE PENDING"
case svc . Paused :
return "PAUSED"
default :
return "UNKNOWN"
}
}
func main () {
if len ( os . Args ) < 2 {
log . Fatal ( "Usage: program <service-name>" )
}
monitorService ( os . Args [ 1 ])
}
Context Support
All query functions have WithContext variants for timeout and cancellation control.
import (
" context "
" time "
" github.com/shirou/gopsutil/v4/winservices "
)
ctx , cancel := context . WithTimeout ( context . Background (), 3 * time . Second )
defer cancel ()
service , err := winservices . NewService ( "wuauserv" )
if err != nil {
log . Fatal ( err )
}
err = service . GetServiceDetailWithContext ( ctx )
if err != nil {
// Handle timeout or cancellation
}
Common Service Names
Some commonly queried Windows services:
wuauserv - Windows Update
Spooler - Print Spooler
Dhcp - DHCP Client
Dnscache - DNS Client
EventLog - Windows Event Log
W32Time - Windows Time
WinDefend - Windows Defender
MSSQLSERVER - SQL Server (if installed)
Requirements
Platform: Windows only (uses //go:build windows build tag)Permissions: Querying service information typically requires:
Standard user privileges for read-only operations
Administrator privileges for sensitive services or system services
Error Handling
Common errors you may encounter:
service , err := winservices . NewService ( "nonexistent" )
if err != nil {
// Handle error - service not found or access denied
log . Printf ( "Error opening service: %v " , err )
}
Errors can occur due to:
Service does not exist
Insufficient permissions
Service Control Manager is unavailable
Invalid service name format
API Reference
The package wraps the following Windows APIs:
OpenSCManager - Opens Service Control Manager
OpenService - Opens a service handle
QueryServiceConfig - Queries service configuration
QueryServiceConfig2 - Queries extended configuration
QueryServiceStatusEx - Queries service status with process info
EnumServicesStatusEx - Enumerates services (via ListServices)
For detailed Windows API documentation, see:
https://docs.microsoft.com/en-us/windows/win32/services/service-functions