...

Source file src/github.com/shirou/gopsutil/winservices/winservices.go

Documentation: github.com/shirou/gopsutil/winservices

     1  // +build windows
     2  
     3  package winservices
     4  
     5  import (
     6  	"context"
     7  	"unsafe"
     8  
     9  	"golang.org/x/sys/windows"
    10  	"golang.org/x/sys/windows/svc"
    11  	"golang.org/x/sys/windows/svc/mgr"
    12  )
    13  
    14  // Service represent a windows service.
    15  type Service struct {
    16  	Name   string
    17  	Config mgr.Config
    18  	Status ServiceStatus
    19  	srv    *mgr.Service
    20  }
    21  
    22  // ServiceStatus combines State and Accepted commands to fully describe running service.
    23  type ServiceStatus struct {
    24  	State         svc.State
    25  	Accepts       svc.Accepted
    26  	Pid           uint32
    27  	Win32ExitCode uint32
    28  }
    29  
    30  // NewService create and return a windows Service
    31  func NewService(name string) (*Service, error) {
    32  	// call windows service function need to OpenService handler,
    33  	// so first call func OpenService to get the specified service handler.
    34  	service, err := getService(name)
    35  	if err != nil {
    36  		return nil, err
    37  	}
    38  	return &Service{
    39  		Name: name,
    40  		srv:  service,
    41  	}, nil
    42  }
    43  
    44  // GetServiceDetail get a windows service by name
    45  func (s *Service) GetServiceDetail() error {
    46  	return s.GetServiceDetailWithContext(context.Background())
    47  }
    48  
    49  // GetServiceDetailWithContext get a windows service by name
    50  func (s *Service) GetServiceDetailWithContext(ctx context.Context) error {
    51  	config, err := s.QueryServiceConfigWithContext(ctx)
    52  	if err != nil {
    53  		return err
    54  	}
    55  	s.Config = config
    56  
    57  	status, err := s.QueryStatusWithContext(ctx)
    58  	if err != nil {
    59  		return err
    60  	}
    61  	s.Status = status
    62  
    63  	return nil
    64  }
    65  
    66  // QueryServiceConfig return the specified service config
    67  func (s *Service) QueryServiceConfig() (mgr.Config, error) {
    68  	return s.QueryServiceConfigWithContext(context.Background())
    69  }
    70  
    71  // QueryServiceConfigWithContext call QueryServiceConfig() and QueryServiceConfig2()
    72  // implement windows https://msdn.microsoft.com/en-us/library/windows/desktop/ms684932(v=vs.85).aspx
    73  func (s *Service) QueryServiceConfigWithContext(ctx context.Context) (mgr.Config, error) {
    74  	return s.srv.Config()
    75  }
    76  
    77  // QueryStatus return the specified name service currentState and ControlsAccepted
    78  func (s *Service) QueryStatus() (ServiceStatus, error) {
    79  	return s.QueryStatusWithContext(context.Background())
    80  }
    81  
    82  // QueryStatusWithContext return the specified name service currentState and ControlsAccepted
    83  func (s *Service) QueryStatusWithContext(ctx context.Context) (ServiceStatus, error) {
    84  	var p *windows.SERVICE_STATUS_PROCESS
    85  	var bytesNeeded uint32
    86  	var buf []byte
    87  
    88  	if err := windows.QueryServiceStatusEx(s.srv.Handle, windows.SC_STATUS_PROCESS_INFO, nil, 0, &bytesNeeded); err != windows.ERROR_INSUFFICIENT_BUFFER {
    89  		return ServiceStatus{}, err
    90  	}
    91  
    92  	buf = make([]byte, bytesNeeded)
    93  	p = (*windows.SERVICE_STATUS_PROCESS)(unsafe.Pointer(&buf[0]))
    94  	if err := windows.QueryServiceStatusEx(s.srv.Handle, windows.SC_STATUS_PROCESS_INFO, &buf[0], uint32(len(buf)), &bytesNeeded); err != nil {
    95  		return ServiceStatus{}, err
    96  	}
    97  
    98  	return ServiceStatus{
    99  		State:         svc.State(p.CurrentState),
   100  		Accepts:       svc.Accepted(p.ControlsAccepted),
   101  		Pid:           p.ProcessId,
   102  		Win32ExitCode: p.Win32ExitCode,
   103  	}, nil
   104  }
   105  
   106  // ListServices return all windows service
   107  // reference to golang.org/x/sys/windows/svc/mgr#ListServices()
   108  func ListServices() ([]Service, error) {
   109  	m, err := openSCManager()
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  	defer m.close()
   114  
   115  	names, err := m.mgr.ListServices()
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  
   120  	services := make([]Service, 0)
   121  	for _, name := range names {
   122  		services = append(services, Service{Name: name})
   123  	}
   124  
   125  	return services, nil
   126  }
   127  

View as plain text