Files
bj_power/bj_power_mes/auto_start.go
T

131 lines
3.3 KiB
Go

package main
import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/registry"
)
var keyPath = `Software\Microsoft\Windows\CurrentVersion\Run`
// resolveExePath 优先用 os.Executable(),回退到 os.Args[0]
// 这能正确处理通过快捷方式 / PATH 启动时 os.Args[0] 不是绝对路径的情况
func resolveExePath() string {
if exe, err := os.Executable(); err == nil {
if abs, err := filepath.Abs(exe); err == nil {
return abs
}
return exe
}
abs, _ := filepath.Abs(os.Args[0])
return abs
}
// 设置开机自启动
// exePath 传入会被忽略,内部一律以 os.Executable() 为准
func setAutoStart(appName string, exePath string) error {
key, _, err := registry.CreateKey(registry.CURRENT_USER, keyPath, registry.ALL_ACCESS) // 当前用户登录后启动
//key, _, err := registry.CreateKey(registry.LOCAL_MACHINE, keyPath, registry.ALL_ACCESS) // 登录前启动(需要管理员权限)
if err != nil {
if errors.Is(err, windows.ERROR_ACCESS_DENIED) {
return err
}
return fmt.Errorf("无法打开注册表键: %v", err)
}
defer key.Close()
// 使用真实的 exe 路径而不是 os.Args[0],避免相对路径
absPath := resolveExePath()
if absPath == "" {
return fmt.Errorf("无法确定可执行文件路径")
}
args := getArgs()
// 路径包含空格时需要加引号
value := fmt.Sprintf(`"%s"`, absPath)
if args != "" {
value = value + " " + args
}
err = key.SetStringValue(appName, value)
if err != nil {
return fmt.Errorf("写入注册表失败: %v", err)
}
return nil
}
// 移除开机自启动
func removeAutoStart(appName string) error {
key, err := registry.OpenKey(registry.CURRENT_USER, keyPath, registry.ALL_ACCESS)
//key, err := registry.OpenKey(registry.LOCAL_MACHINE, keyPath, registry.ALL_ACCESS)
if err != nil {
if errors.Is(err, windows.ERROR_ACCESS_DENIED) {
return err
}
return fmt.Errorf("无法打开注册表键: %v", err)
}
defer key.Close()
err = key.DeleteValue(appName)
if err != nil {
return fmt.Errorf("删除注册表项失败: %v", err)
}
return nil
}
// 检查注册表启动项
func isInRegistry(appName string) (bool, error) {
// 检查当前用户注册表
userKey, err := registry.OpenKey(registry.CURRENT_USER, keyPath, registry.QUERY_VALUE)
if err == nil {
defer userKey.Close()
_, _, err := userKey.GetStringValue(appName)
if err == nil {
return true, nil
}
}
// 检查本地机器注册表(需要管理员权限)
//systemKey, err := registry.OpenKey(registry.LOCAL_MACHINE, keyPath, registry.QUERY_VALUE)
//if err == nil {
// defer systemKey.Close()
// _, _, err := systemKey.GetStringValue(appName)
// if err == nil {
// return true, nil
// }
//}
return false, nil
}
// 综合检查开机启动状态
func isAutoStartEnabled(appName string) bool {
// 检查注册表
if reg, _ := isInRegistry(appName); reg {
return true
}
return false
}
func getArgs() string {
// 构建参数字符串(兼容含空格的参数)
var argsBuilder strings.Builder
for _, arg := range os.Args[1:] {
if strings.ContainsAny(arg, " \t") {
argsBuilder.WriteString(fmt.Sprintf(`"%s" `, arg))
} else {
argsBuilder.WriteString(arg + " ")
}
}
return strings.TrimSpace(argsBuilder.String())
}