Go对windows的相关操作
Salted Fish 2024/5/8 windows
# golang windows程序获取管理员权限
在windows上执行有关系统设置命令的时候需要管理员权限才能操作,比如修改网卡的禁用、启用状态。双击执行是不能正确执行命令的,只有右键以管理员身份运行才能成功,解决这个问题操作如下:
下载rsrc
#项目的terminal执行 Go get github.com/akavel/rsrc1
2把nac.manifest 文件拷贝到当前windows项目根目录
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> <security> <requestedPrivileges> <requestedExecutionLevel level="requireAdministrator"/> </requestedPrivileges> </security> </trustInfo> </assembly>1
2
3
4
5
6
7
8
9
10安装rsrc
#安装完成后在GOPATH的bin下面会有一个rsrc.exe的可执行文件 go install github.com/akavel/rsrc #执行命令出现内容说明安装成功 rsrc1
2
3
4生成nac.syso
#执行完成后项目中会出现nac.syso文件 rsrc -manifest nac.manifest -o nac.syso1
2正常打包即可
# golang 安装证书
// 安装证书---需要管理员权限
func installCa() {
//获取要安装的证书位置
caPath := "/rootCA.pem"
//执行命令
err := cmd.Run("certutil", "-addstore", "root", caPath)
if err != nil {
log.Error("certutil---v%", err)
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
// 运行命令
func Run(name string, arg ...string) error {
cmd := exec.Command(name, arg...)
log.Debug("run cmd: %v", cmd.Args)
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
stdout := new(bytes.Buffer)
stderr := new(bytes.Buffer)
writer := io.MultiWriter(stdout, stderr)
reader := io.MultiReader(stdout, stderr)
cmd.Stdout = writer
cmd.Stderr = writer
decoder := simplifiedchinese.GBK.NewDecoder()
err := cmd.Run()
buf := make([]byte, 4096)
n, _ := reader.Read(buf)
outMsg, _ := decoder.Bytes(buf[:n])
if err != nil {
log.Error("run cmd error: %v, %s", err, outMsg)
} else {
log.Debug("%s", outMsg)
}
return err
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# golang注册系统服务
参考文档:https://cloud.tencent.com/developer/article/2370130
官网文档:https://www.nssm.cc/
# 1、使用nssm安装
下载nssm.exe文件,放入项目中
main方法中进行安装
demo地址
链接:https://pan.baidu.com/s/16cv5eUIJbuEGQ542Es2giQ?pwd=alte 提取码:alte1
2package main import ( "os" "os/exec" "os/signal" "svc-demo/log" "syscall" "time" ) const ( SVC_NAME = "服务名称" SVC_DESC = "服务说明" NSSM = "nssm.exe的路径" ) func main() { if len(os.Args) > 1 { if os.Args[1] == "serve" { //运行程序 serve() } else { log.Errorf("invalid running mode %s", os.Args[1]) } } else { // 注册系统服务 install() } } func install() { log.Info("install service...") executable, _ := os.Executable() // nssm.exe stop svc-demo err := runCommand(NSSM, "stop", SVC_NAME) if err != nil { log.Warnf("stop service failed: %v", err) } // nssm.exe remove svc-demo confirm err = runCommand(NSSM, "remove", SVC_NAME, "confirm") if err != nil { log.Warnf("remove service failed: %v", err) } // nssm.exe install svc-demo "C:\xxx\svc-demo.exe" serve err = runCommand(NSSM, "install", SVC_NAME, executable, "serve") if err != nil { log.Errorf("install service failed: %v", err) } // nssm.exe set NAME Description err = runCommand(NSSM, "set", SVC_NAME, "Description", SVC_DESC) if err != nil { log.Errorf("set service description failed: %v", err) } log.Info("install service success!") // nssm.exe start svc-demo err = runCommand(NSSM, "start", SVC_NAME) if err != nil { log.Errorf("start service failed: %v", err) } } func serve() { log.Info("svc-demo started!") done := make(chan interface{}, 1) go func() { //此地方进行业务逻辑的开发... }() sign := make(chan os.Signal, 1) signal.Notify(sign, syscall.SIGINT, syscall.SIGTERM) done <- <-sign log.Info("svc-demo stopped!") } func runCommand(name string, args ...string) error { log.Debugf("run command: %s %v", name, args) cmd := exec.Command(name, args...) cmd.SysProcAttr = &syscall.SysProcAttr{ HideWindow: true, } if err := cmd.Start(); err != nil { return err } return cmd.Wait() }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# 2、使用github.com/kardianos/service安装
参考文档:
https://www.bilibili.com/video/BV1XN4y1h7sb/?vd_source=7366cbc6dc577f4fde59f655b38c94a1
https://blog.csdn.net/peihexian/article/details/105279057
下载第三方包
go get github.com/kardianos/service //主要用于windows和linux作为服务运行的应用程序 go get github.com/shirou/gopsutil/process //主要用于获取进程信息1
2代码编写
package main import ( "fmt" "github.com/beevik/ntp" "github.com/kardianos/service" "github.com/mako2kano/systime" "os" "time" ) func main(){ //以下为启动windows或者linux 服务相关的配置及初始化代码 svcConfig := &service.Config{ Name: "goNtpClient", //服务名称 DisplayName: "goNtpClient", //服务说明 Description: "自动校时程序", Dependencies: []string{}, //无依赖 } prg := &program{} s, err := service.New(prg, svcConfig) if err != nil { fmt.Println(err.Error()) return } if len(os.Args) > 1 { if os.Args[1] == "install" { s.Install() fmt.Println("服务安装成功") return } if os.Args[1] == "remove" { s.Uninstall() fmt.Println("服务卸载成功") return } fmt.Println("请使用程序名称 install 命令安装为服务,或者程序名称 remove 命令卸载服务!") return } err = s.Run() //会触发Start()函数的执行 if err != nil { fmt.Println(err.Error()) return } } type program struct{} //用于windows/linux service服务控制 func (p *program) Start(s service.Service) error { // Start should not block. Do the actual work async. go p.run() return nil } func (p *program) run() { time.LoadLocation("Asia/Shanghai") for { syncDateTime() time.Sleep(time.Minute*30) } } func (p *program) Stop(s service.Service) error { // Stop should not block. Return with a few seconds. return nil } func syncDateTime() { ntpServerIp:="ntp4.aliyun.com" tm, err := ntp.Time(ntpServerIp) if nil!=err { fmt.Println(err.Error()) return } //fmt.Println(tm.Format("2006-01-02 15:04:05")) err = systime.SetLocalTime(&tm) if nil!=err { fmt.Println(err.Error()) return } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# msi安装包打包工具
advanced installer工具:
https://blog.csdn.net/qq_41750806/article/details/122166802
inno setup:
https://blog.csdn.net/z37411/article/details/129443045