hostSync/cmd/init_windows.go

132 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//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)")
}