[CmdletBinding()] param( [string]$BaseUrl = 'https://workbuddy.tongyuye.com/releases/3.0.1', [string]$InstallRoot = '', [string]$RollbackBackup = '', [string]$LogPath = '', [string]$HumanOrigin = 'native-bootstrap', [switch]$SelfInstall, [switch]$PrepareOnly, [switch]$ForceClose, [switch]$Uninstall ) $ErrorActionPreference = 'Stop' if ($PSVersionTable.PSVersion.Major -le 5) { $env:PSModulePath = @( (Join-Path $env:WINDIR 'System32\WindowsPowerShell\v1.0\Modules'), (Join-Path $env:ProgramFiles 'WindowsPowerShell\Modules') ) -join ';' } [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $taskExpectedZipSha256 = '84f255359e204c40f567f0f34a3e292de1cf71e17e63b1183aedef2c176d16f4' $taskRelease = '3.0.1' $taskDownloadRoot = Join-Path $env:LOCALAPPDATA ('WorkBuddyImageModelPatch\' + $taskRelease + '\download-' + [guid]::NewGuid().ToString('N')) try { if ($taskExpectedZipSha256 -notmatch '^[a-fA-F0-9]{64}$') { throw '发布包尚未写入 SHA256。请从正式下载页面重新获取安装器。' } $taskBase = New-Object Uri($BaseUrl) if ($taskBase.Scheme -ne 'https' -or $taskBase.UserInfo -or $taskBase.Query -or $taskBase.Fragment) { throw '下载地址必须是无凭证、查询参数或片段的 HTTPS 地址。' } [IO.Directory]::CreateDirectory($taskDownloadRoot) | Out-Null $taskZip = Join-Path $taskDownloadRoot 'workbuddy-image-model-patch.zip' Write-Host '正在下载并校验独立安装包。此阶段不会退出或修改 WorkBuddy。' Invoke-WebRequest -UseBasicParsing -Uri ($BaseUrl.TrimEnd('/') + '/workbuddy-image-model-patch.zip') -OutFile $taskZip if ((Get-FileHash -LiteralPath $taskZip -Algorithm SHA256).Hash.ToLowerInvariant() -ne $taskExpectedZipSha256.ToLowerInvariant()) { throw '下载包 SHA256 不匹配,已停止。未退出或修改 WorkBuddy。' } $taskPackage = Join-Path $taskDownloadRoot 'package' Expand-Archive -LiteralPath $taskZip -DestinationPath $taskPackage -Force $taskInstaller = Join-Path $taskPackage 'install.ps1' if (-not [IO.File]::Exists($taskInstaller)) { $taskNested = @(Get-ChildItem -LiteralPath $taskPackage -Filter install.ps1 -File -Recurse) if ($taskNested.Count -ne 1) { throw '下载包没有唯一的本地安装入口。' } $taskInstaller = $taskNested[0].FullName $taskPackage = [IO.Path]::GetDirectoryName($taskInstaller) } $taskArguments = @{ PackageDirectory = [IO.Path]::GetFullPath($taskPackage) HumanOrigin = $HumanOrigin SelfInstall = $SelfInstall PrepareOnly = $PrepareOnly ForceClose = $ForceClose Uninstall = $Uninstall } if ($InstallRoot) { $taskArguments.InstallRoot = [IO.Path]::GetFullPath($InstallRoot) } if ($RollbackBackup) { $taskArguments.RollbackBackup = [IO.Path]::GetFullPath($RollbackBackup) } if ($LogPath) { $taskArguments.LogPath = [IO.Path]::GetFullPath($LogPath) } # Node discovery, native path selection/confirmation, staging, requested UAC, # installation and current-user restart all use the same offline pipeline. & $taskInstaller @taskArguments exit $LASTEXITCODE } catch { $taskError = $_.Exception.Message Write-Host ('FAILED:' + $taskError) if (-not $SelfInstall) { try { Add-Type -AssemblyName System.Windows.Forms [Windows.Forms.MessageBox]::Show($taskError, 'WorkBuddy 图片模型安装器', [Windows.Forms.MessageBoxButtons]::OK, [Windows.Forms.MessageBoxIcon]::Error) | Out-Null } catch {} } exit 1 }