github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/agent/target/service_windows.go (about)

     1  package target
     2  
     3  import (
     4  	"errors"
     5  	"syscall"
     6  	"unsafe"
     7  
     8  	"golang.org/x/sys/windows"
     9  	"golang.org/x/sys/windows/svc/mgr"
    10  )
    11  
    12  // https://docs.microsoft.com/en-us/windows/win32/api/winsvc/nf-winsvc-queryservicestatusex
    13  func getPID(serviceName string) (int, error) {
    14  	m, err := mgr.Connect()
    15  	if err != nil {
    16  		return 0, err
    17  	}
    18  	defer m.Disconnect()
    19  	s, err := m.OpenService(serviceName)
    20  	switch {
    21  	case err == nil:
    22  	case errors.Is(err, syscall.ERROR_NOT_FOUND):
    23  		return 0, ErrNotFound
    24  	default:
    25  		return 0, err
    26  	}
    27  	defer s.Close()
    28  	// A variable that receives the number of bytes needed to store the status
    29  	// information, if the function fails with ERROR_INSUFFICIENT_BUFFER.
    30  	// Not used.
    31  	var needed uint32
    32  	var t windows.SERVICE_STATUS_PROCESS
    33  	err = windows.QueryServiceStatusEx(s.Handle,
    34  		windows.SC_STATUS_PROCESS_INFO,
    35  		(*byte)(unsafe.Pointer(&t)),
    36  		uint32(unsafe.Sizeof(t)),
    37  		&needed)
    38  	if err != nil {
    39  		return 0, err
    40  	}
    41  	if t.ProcessId == 0 {
    42  		return 0, ErrNotRunning
    43  	}
    44  	return int(t.ProcessId), nil
    45  }