132 lines
4.2 KiB
Go
132 lines
4.2 KiB
Go
//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)")
|
||
}
|