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 }