331 lines
9.9 KiB
PowerShell
331 lines
9.9 KiB
PowerShell
# 使用方法: irm "https://git.xykqyy.com/ljp/hostSync/raw/branch/main/install.ps1" | iex
|
||
|
||
# 设置严格模式和错误处理
|
||
Set-StrictMode -Version 3.0
|
||
$ErrorActionPreference = 'Stop'
|
||
|
||
# 默认配置
|
||
$Version = 'latest'
|
||
$InstallDir = "$env:USERPROFILE\.hostsync\bin"
|
||
$NoInit = $false
|
||
$Portable = $false
|
||
|
||
# 颜色输出函数
|
||
function Write-ColorOutput {
|
||
param([string]$Message, [string]$Color = 'White')
|
||
Write-Host $Message -ForegroundColor $Color
|
||
}
|
||
|
||
function Write-Success { param([string]$Message) Write-ColorOutput $Message 'Green' }
|
||
function Write-Info { param([string]$Message) Write-ColorOutput $Message 'Cyan' }
|
||
function Write-Warning { param([string]$Message) Write-ColorOutput $Message 'Yellow' }
|
||
function Write-Error { param([string]$Message) Write-ColorOutput $Message 'Red' }
|
||
|
||
# 检查管理员权限
|
||
function Test-Administrator {
|
||
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||
$principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
|
||
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||
}
|
||
|
||
# 获取最新版本
|
||
function Get-LatestVersion {
|
||
try {
|
||
Write-Info '? 获取最新版本信息...'
|
||
$api = 'https://git.xykqyy.com/api/v1/repos/ljp/hostSync/releases/latest'
|
||
$response = Invoke-RestMethod -Uri $api -ErrorAction Stop
|
||
return $response.tag_name
|
||
}
|
||
catch {
|
||
Write-Warning '?? 无法获取最新版本,使用 v1.0.0'
|
||
return 'v1.0.0'
|
||
}
|
||
}
|
||
|
||
# 检测系统架构
|
||
function Get-Architecture {
|
||
$arch = $env:PROCESSOR_ARCHITECTURE
|
||
switch ($arch) {
|
||
'AMD64' { return 'amd64' }
|
||
'x86' { return '386' }
|
||
'ARM64' { return 'arm64' }
|
||
default { return 'amd64' }
|
||
}
|
||
}
|
||
|
||
# 下载文件
|
||
function Get-FileFromUrl {
|
||
param([string]$Url, [string]$Output)
|
||
|
||
Write-Info "? 下载: $(Split-Path $Output -Leaf)"
|
||
Write-Info "? 地址: $Url"
|
||
|
||
try {
|
||
# 使用 Invoke-WebRequest 下载
|
||
$ProgressPreference = 'SilentlyContinue'
|
||
Invoke-WebRequest -Uri $Url -OutFile $Output -ErrorAction Stop
|
||
$ProgressPreference = 'Continue'
|
||
|
||
if (Test-Path $Output) {
|
||
$size = [math]::Round((Get-Item $Output).Length / 1MB, 2)
|
||
Write-Success "? 下载完成 ($size MB)"
|
||
return $true
|
||
}
|
||
}
|
||
catch {
|
||
Write-Error "? IWR 下载失败: $($_.Exception.Message)"
|
||
# 尝试使用 curl 作为备用方案
|
||
Write-Info '? 尝试使用 curl...'
|
||
try {
|
||
$curlArgs = @('-L', $Url, '-o', $Output, '--silent', '--show-error')
|
||
$curlProcess = Start-Process -FilePath 'curl.exe' -ArgumentList $curlArgs -Wait -PassThru -WindowStyle Hidden
|
||
|
||
if ($curlProcess.ExitCode -eq 0 -and (Test-Path $Output)) {
|
||
Write-Success '? 使用 curl 下载完成'
|
||
return $true
|
||
}
|
||
else {
|
||
Write-Error "? curl 退出码: $($curlProcess.ExitCode)"
|
||
}
|
||
}
|
||
catch {
|
||
Write-Error "? curl 执行失败: $($_.Exception.Message)"
|
||
}
|
||
}
|
||
|
||
return $false
|
||
}
|
||
|
||
# 检查并卸载已有服务
|
||
function Remove-ExistingService {
|
||
Write-Info '? 检查现有安装...'
|
||
|
||
# 检查 PATH 中的 hostsync
|
||
$existingPath = $null
|
||
$pathDirs = $env:PATH -split ';'
|
||
foreach ($dir in $pathDirs) {
|
||
$testPath = Join-Path $dir 'hostsync.exe'
|
||
if (Test-Path $testPath) {
|
||
$existingPath = $testPath
|
||
break
|
||
}
|
||
}
|
||
|
||
# 检查默认安装位置
|
||
if (-not $existingPath) {
|
||
$defaultPath = "$env:USERPROFILE\.hostsync\bin\hostsync.exe"
|
||
if (Test-Path $defaultPath) {
|
||
$existingPath = $defaultPath
|
||
}
|
||
}
|
||
|
||
if ($existingPath) {
|
||
Write-Info "? 发现现有安装: $existingPath"
|
||
|
||
try {
|
||
# 尝试停止并卸载服务
|
||
Write-Info '?? 停止现有服务...'
|
||
$stopArgs = @{
|
||
FilePath = $existingPath
|
||
ArgumentList = @('service', 'stop')
|
||
Wait = $true
|
||
PassThru = $true
|
||
RedirectStandardOutput = $true
|
||
RedirectStandardError = $true
|
||
WindowStyle = 'Hidden'
|
||
}
|
||
Start-Process @stopArgs | Out-Null
|
||
|
||
Write-Info '?? 卸载现有服务...'
|
||
$uninstallArgs = @{
|
||
FilePath = $existingPath
|
||
ArgumentList = @('service', 'uninstall')
|
||
Wait = $true
|
||
PassThru = $true
|
||
RedirectStandardOutput = $true
|
||
RedirectStandardError = $true
|
||
WindowStyle = 'Hidden'
|
||
}
|
||
Start-Process @uninstallArgs | Out-Null
|
||
|
||
Write-Success '? 已清理现有服务'
|
||
}
|
||
catch {
|
||
Write-Warning "?? 清理现有服务时出现错误: $($_.Exception.Message)"
|
||
Write-Info '? 继续安装过程...'
|
||
}
|
||
|
||
# 等待一下确保服务完全停止
|
||
Start-Sleep -Seconds 2
|
||
}
|
||
else {
|
||
Write-Info '? 未发现现有安装'
|
||
}
|
||
}
|
||
|
||
# 主安装函数
|
||
function Install-HostSync {
|
||
Write-ColorOutput @'
|
||
? HostSync 快速安装脚本
|
||
===============================
|
||
强大的 Hosts 文件管理工具
|
||
|
||
功能特点:
|
||
- ? 分块管理 Hosts 配置
|
||
- ? 智能 DNS 解析
|
||
- ? 定时自动更新
|
||
- ? 后台服务运行
|
||
|
||
'@ 'Magenta'
|
||
|
||
# 检查并卸载已有服务
|
||
Remove-ExistingService
|
||
|
||
# 检查管理员权限
|
||
if (-not (Test-Administrator)) {
|
||
Write-Warning '?? 未检测到管理员权限,将跳过服务安装'
|
||
Write-Info '? 如需安装服务,请稍后以管理员身份运行: hostsync service install'
|
||
$NoInit = $true
|
||
}
|
||
|
||
# 确定版本
|
||
if ($Version -eq 'latest') {
|
||
$Version = Get-LatestVersion
|
||
}
|
||
Write-Info "? 安装版本: $Version"# 处理版本号格式 - 确保有v前缀用于tag,去掉v前缀用于文件名
|
||
$TagVersion = $Version
|
||
$FileVersion = $Version
|
||
if ($Version -match '^v(\d+\.\d+\.\d+)$') {
|
||
$TagVersion = $Version
|
||
$FileVersion = $matches[1]
|
||
}
|
||
elseif ($Version -match '^(\d+\.\d+\.\d+)$') {
|
||
$TagVersion = "v$Version"
|
||
$FileVersion = $Version
|
||
}
|
||
|
||
# 确定架构
|
||
$Arch = Get-Architecture
|
||
Write-Info "?? 系统架构: $Arch" # 确定安装目录 (固定为默认位置)
|
||
Write-Info "? 安装目录: $InstallDir"
|
||
|
||
# 创建安装目录
|
||
if (-not (Test-Path $InstallDir)) {
|
||
try {
|
||
New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null
|
||
Write-Success '? 创建安装目录'
|
||
}
|
||
catch {
|
||
Write-Error "? 创建目录失败: $($_.Exception.Message)"
|
||
exit 1
|
||
}
|
||
} # 构建下载 URL
|
||
$FileName = "hostsync-$FileVersion-windows-$Arch.exe"
|
||
$DownloadUrl = "https://git.xykqyy.com/ljp/hostSync/releases/download/$TagVersion/$FileName"
|
||
$OutputFile = Join-Path $InstallDir 'hostsync.exe' # 下载文件
|
||
if (-not (Get-FileFromUrl $DownloadUrl $OutputFile)) {
|
||
Write-Error '? 下载失败,请检查网络连接或手动下载'
|
||
Write-Info '? 手动下载地址: https://git.xykqyy.com/ljp/hostSync/releases'
|
||
exit 1
|
||
}
|
||
|
||
# 验证文件
|
||
if (-not (Test-Path $OutputFile)) {
|
||
Write-Error '? 安装文件不存在'
|
||
exit 1
|
||
}
|
||
|
||
Write-Success '? HostSync 下载完成!' # 添加到 PATH
|
||
Write-Info '? 配置环境变量...'
|
||
|
||
try {
|
||
$currentPath = [Environment]::GetEnvironmentVariable('Path', 'User')
|
||
if ($currentPath -notlike "*$InstallDir*") {
|
||
$newPath = "$currentPath;$InstallDir"
|
||
[Environment]::SetEnvironmentVariable('Path', $newPath, 'User')
|
||
Write-Success '? 已添加到 PATH 环境变量'
|
||
Write-Warning '?? 请重启终端以生效环境变量'
|
||
}
|
||
else {
|
||
Write-Info '? PATH 已包含安装目录'
|
||
}
|
||
}
|
||
catch {
|
||
Write-Warning "?? 设置环境变量失败: $($_.Exception.Message)"
|
||
Write-Info "? 你可以手动将 '$InstallDir' 添加到 PATH"
|
||
}# 运行初始化
|
||
if (-not $NoInit) {
|
||
Write-Info '? 开始初始化 HostSync...'
|
||
|
||
try {
|
||
# 使用 Start-Process 来更好地控制进程执行
|
||
Write-Info "? 执行命令: $OutputFile init"
|
||
|
||
$processArgs = @{
|
||
FilePath = $OutputFile
|
||
ArgumentList = @('init')
|
||
Wait = $true
|
||
PassThru = $true
|
||
RedirectStandardOutput = $true
|
||
RedirectStandardError = $true
|
||
WindowStyle = 'Hidden'
|
||
}
|
||
|
||
$process = Start-Process @processArgs
|
||
|
||
if ($process.ExitCode -eq 0) {
|
||
Write-Success '? 初始化完成!'
|
||
}
|
||
else {
|
||
Write-Warning "?? 初始化退出码: $($process.ExitCode)"
|
||
Write-Info '? 可能需要管理员权限,你可以稍后手动运行:'
|
||
Write-Info ' 以管理员身份打开 PowerShell'
|
||
Write-Info ' 运行: hostsync init'
|
||
}
|
||
}
|
||
catch {
|
||
Write-Warning "?? 初始化过程出现异常: $($_.Exception.Message)"
|
||
Write-Info '? 请尝试手动初始化:'
|
||
Write-Info ' 1. 以管理员身份打开 PowerShell'
|
||
Write-Info " 2. 运行: `"$OutputFile`" init"
|
||
Write-Info ' 3. 或者: hostsync init (如果已添加到PATH)'
|
||
}
|
||
}
|
||
|
||
# 显示完成信息
|
||
Write-Success @"
|
||
|
||
? HostSync 安装完成!
|
||
=====================
|
||
|
||
? 安装位置: $OutputFile
|
||
? 配置目录: $env:USERPROFILE\.hostsync\
|
||
|
||
? 快速开始:
|
||
"@
|
||
|
||
Write-Info ' hostsync list # 查看配置'
|
||
Write-Info ' hostsync add test example.com # 添加域名'
|
||
Write-Info @'
|
||
hostsync update # 更新解析
|
||
hostsync service status # 查看服务状态
|
||
|
||
? 更多帮助:
|
||
hostsync help # 查看帮助
|
||
hostsync version # 查看版本
|
||
|
||
? 项目地址: https://git.xykqyy.com/ljp/hostSync
|
||
'@
|
||
}
|
||
|
||
# 错误处理
|
||
trap {
|
||
Write-Error "? 安装过程中发生错误: $($_.Exception.Message)"
|
||
Write-Info '? 请检查网络连接或手动下载安装'
|
||
exit 1
|
||
}
|
||
|
||
# 执行安装
|
||
Remove-ExistingService
|
||
Install-HostSync
|