github.com/TeaOSLab/EdgeNode@v1.3.8/internal/utils/service_windows.go (about)

     1  //go:build windows
     2  // +build windows
     3  
     4  package utils
     5  
     6  import (
     7  	"fmt"
     8  	teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
     9  	"github.com/iwind/TeaGo/Tea"
    10  	"golang.org/x/sys/windows"
    11  	"golang.org/x/sys/windows/svc"
    12  	"golang.org/x/sys/windows/svc/mgr"
    13  	"os/exec"
    14  )
    15  
    16  // 安装服务
    17  func (this *ServiceManager) Install(exePath string, args []string) error {
    18  	m, err := mgr.Connect()
    19  	if err != nil {
    20  		return fmt.Errorf("connecting: %w please 'Run as administrator' again", err)
    21  	}
    22  	defer m.Disconnect()
    23  	s, err := m.OpenService(this.Name)
    24  	if err == nil {
    25  		s.Close()
    26  		return fmt.Errorf("service %s already exists", this.Name)
    27  	}
    28  
    29  	s, err = m.CreateService(this.Name, exePath, mgr.Config{
    30  		DisplayName: this.Name,
    31  		Description: this.Description,
    32  		StartType:   windows.SERVICE_AUTO_START,
    33  	}, args...)
    34  	if err != nil {
    35  		return fmt.Errorf("creating: %w", err)
    36  	}
    37  	defer s.Close()
    38  
    39  	return nil
    40  }
    41  
    42  // 启动服务
    43  func (this *ServiceManager) Start() error {
    44  	m, err := mgr.Connect()
    45  	if err != nil {
    46  		return err
    47  	}
    48  	defer m.Disconnect()
    49  	s, err := m.OpenService(this.Name)
    50  	if err != nil {
    51  		return fmt.Errorf("could not access service: %w", err)
    52  	}
    53  	defer s.Close()
    54  	err = s.Start("service")
    55  	if err != nil {
    56  		return fmt.Errorf("could not start service: %w", err)
    57  	}
    58  
    59  	return nil
    60  }
    61  
    62  // 删除服务
    63  func (this *ServiceManager) Uninstall() error {
    64  	m, err := mgr.Connect()
    65  	if err != nil {
    66  		return fmt.Errorf("connecting: %w please 'Run as administrator' again", err)
    67  	}
    68  	defer m.Disconnect()
    69  	s, err := m.OpenService(this.Name)
    70  	if err != nil {
    71  		return fmt.Errorf("open service: %w", err)
    72  	}
    73  
    74  	// shutdown service
    75  	_, err = s.Control(svc.Stop)
    76  	if err != nil {
    77  		fmt.Printf("shutdown service: %s\n", err.Error())
    78  	}
    79  
    80  	defer s.Close()
    81  	err = s.Delete()
    82  	if err != nil {
    83  		return fmt.Errorf("deleting: %w", err)
    84  	}
    85  	return nil
    86  }
    87  
    88  // 运行
    89  func (this *ServiceManager) Run() {
    90  	err := svc.Run(this.Name, this)
    91  	if err != nil {
    92  		this.LogError(err.Error())
    93  	}
    94  }
    95  
    96  // 同服务管理器的交互
    97  func (this *ServiceManager) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) {
    98  	const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown | svc.AcceptPauseAndContinue
    99  
   100  	changes <- svc.Status{
   101  		State: svc.StartPending,
   102  	}
   103  
   104  	changes <- svc.Status{
   105  		State:   svc.Running,
   106  		Accepts: cmdsAccepted,
   107  	}
   108  
   109  	// start service
   110  	this.Log("start")
   111  	this.cmdStart()
   112  
   113  loop:
   114  	for {
   115  		select {
   116  		case c := <-r:
   117  			switch c.Cmd {
   118  			case svc.Interrogate:
   119  				this.Log("cmd: Interrogate")
   120  				changes <- c.CurrentStatus
   121  			case svc.Stop, svc.Shutdown:
   122  				this.Log("cmd: Stop|Shutdown")
   123  
   124  				// stop service
   125  				this.cmdStop()
   126  
   127  				break loop
   128  			case svc.Pause:
   129  				this.Log("cmd: Pause")
   130  
   131  				// stop service
   132  				this.cmdStop()
   133  
   134  				changes <- svc.Status{
   135  					State:   svc.Paused,
   136  					Accepts: cmdsAccepted,
   137  				}
   138  			case svc.Continue:
   139  				this.Log("cmd: Continue")
   140  
   141  				// start service
   142  				this.cmdStart()
   143  
   144  				changes <- svc.Status{
   145  					State:   svc.Running,
   146  					Accepts: cmdsAccepted,
   147  				}
   148  			default:
   149  				this.LogError(fmt.Sprintf("unexpected control request #%d\r\n", c))
   150  			}
   151  		}
   152  	}
   153  	changes <- svc.Status{
   154  		State: svc.StopPending,
   155  	}
   156  	return
   157  }
   158  
   159  // 启动Web服务
   160  func (this *ServiceManager) cmdStart() {
   161  	cmd := exec.Command(Tea.Root+Tea.DS+"bin"+Tea.DS+teaconst.SystemdServiceName+".exe", "start")
   162  	err := cmd.Start()
   163  	if err != nil {
   164  		this.LogError(err.Error())
   165  	}
   166  }
   167  
   168  // 停止Web服务
   169  func (this *ServiceManager) cmdStop() {
   170  	cmd := exec.Command(Tea.Root+Tea.DS+"bin"+Tea.DS+teaconst.SystemdServiceName+".exe", "stop")
   171  	err := cmd.Start()
   172  	if err != nil {
   173  		this.LogError(err.Error())
   174  	}
   175  }