🐛 Fixed bug

This commit is contained in:
2025-06-21 15:03:35 +08:00
parent 145b868a44
commit 1153c0a652
22 changed files with 646 additions and 309 deletions

View File

@@ -0,0 +1,151 @@
//go:build windows
package services
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/wailsapp/wails/v3/pkg/services/log"
"golang.org/x/sys/windows/registry"
)
// WindowsStartupImpl Windows 平台开机启动实现
type WindowsStartupImpl struct {
logger *log.LoggerService
registryKey string
execPath string
workingDir string
batchFile string
}
// newStartupImplementation 创建平台特定的开机启动实现
func newStartupImplementation(logger *log.LoggerService) StartupImplementation {
return &WindowsStartupImpl{
logger: logger,
}
}
// Initialize 初始化 Windows 实现
func (w *WindowsStartupImpl) Initialize() error {
exePath, err := os.Executable()
if err != nil {
return fmt.Errorf("failed to get executable path: %w", err)
}
// 获取绝对路径并规范化
absPath, err := filepath.Abs(exePath)
if err != nil {
return fmt.Errorf("failed to get absolute path: %w", err)
}
// 转换为Windows标准路径格式
w.execPath = filepath.ToSlash(absPath)
w.execPath = strings.ReplaceAll(w.execPath, "/", "\\")
// 获取工作目录(可执行文件所在目录)
w.workingDir = filepath.Dir(w.execPath)
// 使用文件名作为注册表键名
w.registryKey = strings.TrimSuffix(filepath.Base(w.execPath), filepath.Ext(w.execPath))
// 批处理文件路径(放在临时目录)
tempDir := os.TempDir()
w.batchFile = filepath.Join(tempDir, w.registryKey+"_startup.bat")
return nil
}
// openRegistryKey 打开注册表键
func (w *WindowsStartupImpl) openRegistryKey() (registry.Key, error) {
key, err := registry.OpenKey(
registry.CURRENT_USER,
`Software\Microsoft\Windows\CurrentVersion\Run`,
registry.ALL_ACCESS,
)
if err != nil {
return 0, fmt.Errorf("failed to open registry key: %w", err)
}
return key, nil
}
// createBatchFile 创建批处理文件
func (w *WindowsStartupImpl) createBatchFile() error {
// 批处理文件内容
batchContent := fmt.Sprintf(`@echo off
cd /d "%s"
start "" "%s"
`, w.workingDir, w.execPath)
// 写入批处理文件
if err := os.WriteFile(w.batchFile, []byte(batchContent), 0644); err != nil {
return fmt.Errorf("failed to create batch file: %w", err)
}
return nil
}
// deleteBatchFile 删除批处理文件
func (w *WindowsStartupImpl) deleteBatchFile() {
if _, err := os.Stat(w.batchFile); err == nil {
os.Remove(w.batchFile)
}
}
// buildStartupCommand 构建启动命令
func (w *WindowsStartupImpl) buildStartupCommand() (string, error) {
// 尝试直接使用可执行文件路径
execPath := w.execPath
if strings.Contains(execPath, " ") {
execPath = `"` + execPath + `"`
}
// 首先尝试直接路径,如果有问题再使用批处理文件
return execPath, nil
}
// SetEnabled 设置开机启动状态
func (w *WindowsStartupImpl) SetEnabled(enabled bool) error {
key, err := w.openRegistryKey()
if err != nil {
return fmt.Errorf("failed to access registry: %w", err)
}
defer key.Close()
if enabled {
startupCmd, err := w.buildStartupCommand()
if err != nil {
return fmt.Errorf("failed to build startup command: %w", err)
}
w.logger.Info("Setting Windows startup", "command", startupCmd)
if err := key.SetStringValue(w.registryKey, startupCmd); err != nil {
return fmt.Errorf("failed to set startup entry: %w", err)
}
// 验证设置是否成功
if value, _, err := key.GetStringValue(w.registryKey); err != nil {
return fmt.Errorf("startup entry verification failed: %w", err)
} else if value != startupCmd {
w.logger.Error("Startup command verification mismatch", "expected", startupCmd, "actual", value)
}
w.logger.Info("Windows startup enabled successfully")
} else {
// 删除批处理文件(如果存在)
w.deleteBatchFile()
if err := key.DeleteValue(w.registryKey); err != nil {
// 如果键不存在,这不是错误
if err != registry.ErrNotExist {
return fmt.Errorf("failed to remove startup entry: %w", err)
}
}
w.logger.Info("Windows startup disabled successfully")
}
return nil
}