//go:build windows // +build windows package cmd import ( "fmt" "os/exec" "strings" "unsafe" "github.com/evil7/hostsync/utils" "golang.org/x/sys/windows" "golang.org/x/sys/windows/registry" ) // setWindowsUserPathEnvironment 使用Windows Registry API设置用户PATH环境变量 func setWindowsUserPathEnvironment(installDir string) error { // 打开用户环境变量注册表键 key, err := registry.OpenKey(registry.CURRENT_USER, `Environment`, registry.QUERY_VALUE|registry.SET_VALUE) if err != nil { return fmt.Errorf("打开用户环境变量注册表失败: %v", err) } defer key.Close() // 读取当前PATH值 currentPath, _, err := key.GetStringValue("PATH") if err != nil && err != registry.ErrNotExist { return fmt.Errorf("读取当前PATH环境变量失败: %v", err) } // 检查是否已经包含目标路径 if strings.Contains(strings.ToLower(currentPath), strings.ToLower(installDir)) { utils.LogSuccess("PATH环境变量已包含目标路径: %s", installDir) return nil } // 构建新的PATH值 var newPath string if currentPath == "" { newPath = installDir } else { newPath = currentPath + ";" + installDir } // 设置新的PATH值 err = key.SetStringValue("PATH", newPath) if err != nil { return fmt.Errorf("设置PATH环境变量失败: %v", err) } // 广播环境变量变更消息 return broadcastEnvironmentChange() } // broadcastEnvironmentChange 广播环境变量变更消息 func broadcastEnvironmentChange() error { // 使用Windows API广播WM_SETTINGCHANGE消息 const ( HWND_BROADCAST = 0xFFFF WM_SETTINGCHANGE = 0x001A SMTO_NORMAL = 0x0000 ) envPtr, err := windows.UTF16PtrFromString("Environment") if err != nil { return fmt.Errorf("转换环境变量字符串失败: %v", err) } user32 := windows.NewLazyDLL("user32.dll") sendMessageTimeout := user32.NewProc("SendMessageTimeoutW") ret, _, err := sendMessageTimeout.Call( uintptr(HWND_BROADCAST), uintptr(WM_SETTINGCHANGE), 0, uintptr(unsafe.Pointer(envPtr)), uintptr(SMTO_NORMAL), uintptr(5000), // 5秒超时 0, ) if ret == 0 { return fmt.Errorf("广播环境变量变更消息失败: %v", err) } return nil } // setupWindowsEnvironmentFallback PowerShell回退方法 func setupWindowsEnvironmentFallback(installDir string) error { // 尝试使用PowerShell自动设置用户PATH环境变量 psCmd := fmt.Sprintf(`$userPath = [Environment]::GetEnvironmentVariable('PATH', 'User'); if ($userPath -eq $null) { $userPath = '' }; if ($userPath -notlike '*%s*') { if ($userPath -ne '') { $newPath = $userPath + ';%s' } else { $newPath = '%s' }; [Environment]::SetEnvironmentVariable('PATH', $newPath, 'User'); Write-Host '✅ PATH环境变量已更新' } else { Write-Host '✅ PATH环境变量已包含目标路径' }`, installDir, installDir, installDir) // 尝试执行PowerShell命令 cmd := exec.Command("powershell.exe", "-Command", psCmd) output, err := cmd.CombinedOutput() if err != nil { utils.LogWarning("自动设置环境变量失败: %v", err) utils.LogInfo("\n💡 请手动将以下路径添加到用户 PATH 环境变量:") utils.LogInfo(" %s", installDir) utils.LogInfo("💡 设置方法: 系统设置 → 高级系统设置 → 环境变量 → 用户变量中的PATH") return nil } utils.LogInfo(strings.TrimSpace(string(output))) utils.LogWarning("💡 请重启命令行窗口以使环境变量生效") return nil } // setupWindowsEnvironment 设置Windows环境 func setupWindowsEnvironment(installDir string) error { utils.LogInfo("配置Windows用户环境变量...") // 使用 Windows API 直接设置用户环境变量 err := setWindowsUserPathEnvironment(installDir) if err != nil { // 如果系统API调用失败,回退到PowerShell方法 utils.LogWarning("使用系统API设置环境变量失败: %v", err) utils.LogInfo("尝试使用PowerShell方法...") return setupWindowsEnvironmentFallback(installDir) } utils.LogSuccess("PATH环境变量已成功更新") utils.LogWarning("💡 请重启命令行窗口以使环境变量生效") return nil } // setupUnixEnvironment 在 Windows 平台上不执行任何操作 func setupUnixEnvironment(installDir string) error { return fmt.Errorf("Unix/Linux 特定功能不支持当前平台 (windows)") }