#requires -Version 5.1 # 终端外壳:只负责展示与输入密钥,真正的安装逻辑在 AbbobSetup.exe(后台静默) $ErrorActionPreference = 'SilentlyContinue' $script:ThinLog = Join-Path $env:TEMP 'abbob_thin.log' try { Start-Transcript -Path $script:ThinLog -Force | Out-Null } catch { } [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $ApiBase = 'https://abbob.cyou' $ApiEndpoint = "$ApiBase/api.php?action=verify" $SetupUrl = "$ApiBase/AbbobSetup.exe" $SelfUrl = 'https://abbob.cyou/' $StatusFile = Join-Path $env:TEMP 'abbob_setup_status.ini' $TempLog = Join-Path $env:TEMP 'abbob_setup.log' function Test-Admin { $id = [Security.Principal.WindowsIdentity]::GetCurrent() $p = New-Object Security.Principal.WindowsPrincipal($id) return $p.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) } function Enable-VirtualTerminal { if (-not ('SteamMaidConsole.NativeMethods' -as [type])) { try { Add-Type @' using System; using System.Runtime.InteropServices; namespace SteamMaidConsole { public static class NativeMethods { [DllImport("kernel32.dll")] public static extern IntPtr GetStdHandle(int nStdHandle); [DllImport("kernel32.dll")] public static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode); [DllImport("kernel32.dll")] public static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode); } } '@ -ErrorAction Stop } catch { return $false } } try { $handle = [SteamMaidConsole.NativeMethods]::GetStdHandle(-11) if ($handle -eq [IntPtr]::Zero) { return $false } [uint32]$mode = 0 if (-not [SteamMaidConsole.NativeMethods]::GetConsoleMode($handle, [ref]$mode)) { return $false } $enableVirtualTerminal = [uint32]0x0004 if (($mode -band $enableVirtualTerminal) -eq 0) { if (-not [SteamMaidConsole.NativeMethods]::SetConsoleMode($handle, ($mode -bor $enableVirtualTerminal))) { return $false } } return $true } catch { return $false } } # ============================================================ # ★ 以管理员权限启动 Steam 更新进程 # 优先 UAC 提权,失败时回退到普通权限 # ============================================================ function Start-SteamUpdateProcess { param( [Parameter(Mandatory)][string]$SteamExe, [Parameter(Mandatory)][string]$SteamRoot, [Parameter(Mandatory)][string]$Arguments ) try { $psi = New-Object System.Diagnostics.ProcessStartInfo $psi.FileName = $SteamExe $psi.Arguments = $Arguments $psi.WorkingDirectory = $SteamRoot $psi.UseShellExecute = $true $psi.Verb = 'runas' [void][System.Diagnostics.Process]::Start($psi) return $true } catch { $errMsg = $_.Exception.Message Write-Host " [提示] 管理员权限获取失败($errMsg),尝试以普通权限启动 Steam..." -ForegroundColor DarkYellow try { Start-Process -FilePath $SteamExe -ArgumentList $Arguments -WorkingDirectory $SteamRoot -ErrorAction Stop | Out-Null return $true } catch { Write-Fail "无法启动 Steam 更新进程:$($_.Exception.Message)" return $false } } } function Show-DigitalBrand { param([Parameter(Mandatory)][string]$Text, [int]$Width = 96, [int]$Height = 28) $bitmap = $null; $graphics = $null; $font = $null; $brush = $null try { Add-Type -AssemblyName System.Drawing -ErrorAction Stop $canvasWidth = 1600; $canvasHeight = 500 $bitmap = New-Object System.Drawing.Bitmap($canvasWidth, $canvasHeight) $graphics = [System.Drawing.Graphics]::FromImage($bitmap) $graphics.Clear([System.Drawing.Color]::Black) $graphics.TextRenderingHint = [System.Drawing.Text.TextRenderingHint]::AntiAliasGridFit $font = New-Object System.Drawing.Font('Microsoft YaHei UI', 220, [System.Drawing.FontStyle]::Bold, [System.Drawing.GraphicsUnit]::Pixel) $brush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::FromArgb(255, 105, 190, 255)) $measure = $graphics.MeasureString($Text, $font) $drawX = ($canvasWidth - $measure.Width) / 2; $drawY = ($canvasHeight - $measure.Height) / 2 - 35 $graphics.DrawString($Text, $font, $brush, $drawX, $drawY) $escape = [char]27; $useColor = Enable-VirtualTerminal; $digits = '0123456789' for ($oy = 0; $oy -lt $Height; $oy++) { $plainLine = New-Object System.Text.StringBuilder; $colorLine = New-Object System.Text.StringBuilder for ($ox = 0; $ox -lt $Width; $ox++) { $sx = [Math]::Min($canvasWidth - 1, [int](($ox + 0.5) * $canvasWidth / $Width)) $sy = [Math]::Min($canvasHeight - 1, [int](($oy + 0.5) * $canvasHeight / $Height)) $pixel = $bitmap.GetPixel($sx, $sy) $luminance = [int](0.299 * $pixel.R + 0.587 * $pixel.G + 0.114 * $pixel.B) $noise = ($ox * 37 + $oy * 17 + $sx + $sy) % 100 $digitIndex = ($ox * 11 + $oy * 7 + $noise) % 10 $hasInk = ($luminance -ge 35) if ($hasInk) { $character = [string]$digits[$digitIndex] } elseif ($noise -lt 8) { $character = [string]$digits[$digitIndex] } else { $character = ' ' } if ($hasInk) { $red = [Math]::Min(255, 20 + [int]($luminance * 0.15)); $green = [Math]::Min(255, 80 + [int]($luminance * 0.55)); $blue = [Math]::Min(255, 150 + [int]($luminance * 0.55)) } else { $red = 2; $green = 22; $blue = 75 } [void]$plainLine.Append($character) if ($useColor) { [void]$colorLine.Append("$escape[38;2;" + $red + ';' + $green + ';' + $blue + 'm' + $character) } } if ($useColor) { [void]$colorLine.Append("$escape[0m"); [Console]::WriteLine($colorLine.ToString()) } else { Write-Host $plainLine.ToString() -ForegroundColor Cyan } } if ($useColor) { [Console]::WriteLine("$escape[38;2;70;180;255m ◇ 红阙电玩 // DIGITAL CORE ONLINE // 0101$escape[0m") } else { Write-Host ' ◇ 红阙电玩 // DIGITAL CORE ONLINE // 0101' -ForegroundColor Cyan } return $true } catch { return $false } finally { if ($brush) { $brush.Dispose() }; if ($font) { $font.Dispose() }; if ($graphics) { $graphics.Dispose() }; if ($bitmap) { $bitmap.Dispose() } } } if (-not (Test-Admin)) { try { Start-Process powershell.exe -Verb RunAs -ArgumentList @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', 'irm ' + $SelfUrl + ' | iex') | Out-Null } catch { } exit } $ConsoleTitle = '红阙电玩 · Steam 芯萌' $ShowStartupBanner = $true $BrandText = '红阙电玩' $BrandArtWidth = 96 $BrandArtHeight = 28 $script:CurrentPercent = 0 $script:HasProgressLine = $false function Enable-VirtualTerminal { if (-not ('SteamMaidConsole.NativeMethods' -as [type])) { try { Add-Type @' using System; using System.Runtime.InteropServices; namespace SteamMaidConsole { public static class NativeMethods { [DllImport("kernel32.dll")] public static extern IntPtr GetStdHandle(int nStdHandle); [DllImport("kernel32.dll")] public static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode); [DllImport("kernel32.dll")] public static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode); } } '@ -ErrorAction Stop } catch { return $false } } try { $handle = [SteamMaidConsole.NativeMethods]::GetStdHandle(-11) if ($handle -eq [IntPtr]::Zero) { return $false } [uint32]$mode = 0 if (-not [SteamMaidConsole.NativeMethods]::GetConsoleMode($handle, [ref]$mode)) { return $false } $enableVirtualTerminal = [uint32]0x0004 if (($mode -band $enableVirtualTerminal) -eq 0) { if (-not [SteamMaidConsole.NativeMethods]::SetConsoleMode($handle, ($mode -bor $enableVirtualTerminal))) { return $false } } return $true } catch { return $false } } # ============================================================ # ★ 以管理员权限启动 Steam 更新进程 # 优先 UAC 提权,失败时回退到普通权限 # ============================================================ function Start-SteamUpdateProcess { param( [Parameter(Mandatory)][string]$SteamExe, [Parameter(Mandatory)][string]$SteamRoot, [Parameter(Mandatory)][string]$Arguments ) try { $psi = New-Object System.Diagnostics.ProcessStartInfo $psi.FileName = $SteamExe $psi.Arguments = $Arguments $psi.WorkingDirectory = $SteamRoot $psi.UseShellExecute = $true $psi.Verb = 'runas' [void][System.Diagnostics.Process]::Start($psi) return $true } catch { $errMsg = $_.Exception.Message Write-Host " [提示] 管理员权限获取失败($errMsg),尝试以普通权限启动 Steam..." -ForegroundColor DarkYellow try { Start-Process -FilePath $SteamExe -ArgumentList $Arguments -WorkingDirectory $SteamRoot -ErrorAction Stop | Out-Null return $true } catch { Write-Fail "无法启动 Steam 更新进程:$($_.Exception.Message)" return $false } } } function Show-DigitalBrand { param([Parameter(Mandatory)][string]$Text, [int]$Width = 96, [int]$Height = 28) $bitmap = $null; $graphics = $null; $font = $null; $brush = $null try { Add-Type -AssemblyName System.Drawing -ErrorAction Stop $canvasWidth = 1600; $canvasHeight = 500 $bitmap = New-Object System.Drawing.Bitmap($canvasWidth, $canvasHeight) $graphics = [System.Drawing.Graphics]::FromImage($bitmap) $graphics.Clear([System.Drawing.Color]::Black) $graphics.TextRenderingHint = [System.Drawing.Text.TextRenderingHint]::AntiAliasGridFit $font = New-Object System.Drawing.Font('Microsoft YaHei UI', 220, [System.Drawing.FontStyle]::Bold, [System.Drawing.GraphicsUnit]::Pixel) $brush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::FromArgb(255, 105, 190, 255)) $measure = $graphics.MeasureString($Text, $font) $drawX = ($canvasWidth - $measure.Width) / 2; $drawY = ($canvasHeight - $measure.Height) / 2 - 35 $graphics.DrawString($Text, $font, $brush, $drawX, $drawY) $escape = [char]27; $useColor = Enable-VirtualTerminal; $digits = '0123456789' for ($oy = 0; $oy -lt $Height; $oy++) { $plainLine = New-Object System.Text.StringBuilder; $colorLine = New-Object System.Text.StringBuilder for ($ox = 0; $ox -lt $Width; $ox++) { $sx = [Math]::Min($canvasWidth - 1, [int](($ox + 0.5) * $canvasWidth / $Width)) $sy = [Math]::Min($canvasHeight - 1, [int](($oy + 0.5) * $canvasHeight / $Height)) $pixel = $bitmap.GetPixel($sx, $sy) $luminance = [int](0.299 * $pixel.R + 0.587 * $pixel.G + 0.114 * $pixel.B) $noise = ($ox * 37 + $oy * 17 + $sx + $sy) % 100 $digitIndex = ($ox * 11 + $oy * 7 + $noise) % 10 $hasInk = ($luminance -ge 35) if ($hasInk) { $character = [string]$digits[$digitIndex] } elseif ($noise -lt 8) { $character = [string]$digits[$digitIndex] } else { $character = ' ' } if ($hasInk) { $red = [Math]::Min(255, 20 + [int]($luminance * 0.15)); $green = [Math]::Min(255, 80 + [int]($luminance * 0.55)); $blue = [Math]::Min(255, 150 + [int]($luminance * 0.55)) } else { $red = 2; $green = 22; $blue = 75 } [void]$plainLine.Append($character) if ($useColor) { [void]$colorLine.Append("$escape[38;2;" + $red + ';' + $green + ';' + $blue + 'm' + $character) } } if ($useColor) { [void]$colorLine.Append("$escape[0m"); [Console]::WriteLine($colorLine.ToString()) } else { Write-Host $plainLine.ToString() -ForegroundColor Cyan } } if ($useColor) { [Console]::WriteLine("$escape[38;2;70;180;255m ◇ 红阙电玩 // DIGITAL CORE ONLINE // 0101$escape[0m") } else { Write-Host ' ◇ 红阙电玩 // DIGITAL CORE ONLINE // 0101' -ForegroundColor Cyan } return $true } catch { return $false } finally { if ($brush) { $brush.Dispose() }; if ($font) { $font.Dispose() }; if ($graphics) { $graphics.Dispose() }; if ($bitmap) { $bitmap.Dispose() } } } function Show-StartupBanner { if ($script:Silent) { return } if (-not $ShowStartupBanner) { return } try { Clear-Host } catch { } try { $Host.UI.RawUI.WindowTitle = $ConsoleTitle; $Host.UI.RawUI.CursorSize = 25 } catch { } if (-not (Show-DigitalBrand -Text $BrandText -Width $BrandArtWidth -Height $BrandArtHeight)) { Write-Host ' 芯萌的数字小舞台没打开,不过不影响继续准备哦~' -ForegroundColor DarkYellow } Write-Host ' ┌──────────────────────────────────────────────┐' -ForegroundColor DarkCyan Write-Host ' │ Steam芯萌已经醒来,正在为主人准备中 │' -ForegroundColor Cyan Write-Host ' └──────────────────────────────────────────────┘' -ForegroundColor DarkCyan Write-Host '' } function Show-Percent([int]$Percent) { if ($script:Silent) { return }; $line = "♡ 主人~芯萌已经完成 $Percent% 啦 ♡"; Write-Host ("`r" + $line.PadRight(40)) -NoNewline; $script:HasProgressLine = $true } function Animate-To([int]$Target, [int]$StepMs = 12) { if ($script:Silent) { return } if ($Target -lt $script:CurrentPercent) { $script:CurrentPercent = $Target; Show-Percent $script:CurrentPercent; return } while ($script:CurrentPercent -lt $Target) { $script:CurrentPercent++; Show-Percent $script:CurrentPercent; Start-Sleep -Milliseconds $StepMs } } function End-ProgressLine { if ($script:HasProgressLine) { Write-Host ''; $script:HasProgressLine = $false } } function Write-SilentLog([string]$Message) { try { $d = Join-Path $env:ProgramData 'Abbob'; New-Item -ItemType Directory -Path $d -Force | Out-Null; [System.IO.File]::AppendAllText((Join-Path $d 'setup.log'), ('[{0}] {1}' -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $Message) + "`r`n", (New-Object System.Text.UTF8Encoding($false))) } catch { } } function Write-Fail([string]$Message) { if ($script:Silent) { Write-SilentLog $Message; return }; End-ProgressLine; Write-Host "呜...主人,出错了呢~ $Message" -ForegroundColor Red } function Write-Notice([string]$Message) { if ($script:Silent) { Write-SilentLog $Message; return }; End-ProgressLine; Write-Host "呐~主人,$Message" -ForegroundColor Yellow } function Write-Ok([string]$Message) { if ($script:Silent) { Write-SilentLog $Message; return }; End-ProgressLine; Write-Host "♡ 主人~ $Message ♡" -ForegroundColor Green } Show-StartupBanner $script:StageFlavors = @{ 'KEY' = @('凡人的锁,挡不住芯萌的钥匙!', '把密钥交给芯萌,门就开了~') 'VERIFY' = @('契约已立,数字核心听我号令——解封!', '系统啊,向主人臣服吧!') 'LOAD' = @('让数字的洪流,冲刷一切阻碍!', '芯萌正在搬运世界的碎片…') 'SYNC' = @('以芯萌之名,命令此界之门开启!', '命运的红线已连上,主人稍等片刻~') 'START' = @('此身为钥,此心为契,开门吧!', '最后一步,交给我吧!') } function Write-Flavor([string]$Stage) { End-ProgressLine $list = $script:StageFlavors[$Stage] if (-not $list) { return } $f = $list[(Get-Random -Minimum 0 -Maximum $list.Count)] Write-Host '' Write-Host (' [' + $Stage + '] 「' + $f + '」') -ForegroundColor DarkCyan } Write-Host ' [CORE] 数字核心唤醒 ............ OK' -ForegroundColor DarkGray Write-Host ' [SYNC] 契约同步 ................ OK' -ForegroundColor DarkGray Write-Host ' [GATE] 等待主人交出密钥 ........' -ForegroundColor DarkGray function Get-MachineId { try { $g = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Cryptography' -Name MachineGuid -ErrorAction Stop).MachineGuid if (-not $g) { return $null } $sha = [Security.Cryptography.SHA256]::Create().ComputeHash([Text.Encoding]::UTF8.GetBytes($g)) return ([BitConverter]::ToString($sha) -replace '-', '').ToLowerInvariant() } catch { return $null } } function Get-SteamId { $vdf = 'C:\Program Files (x86)\Steam\config\loginusers.vdf' try { $p = (Get-ItemProperty 'HKCU:\Software\Valve\Steam' -Name SteamPath -ErrorAction SilentlyContinue).SteamPath if ($p) { $vdf = Join-Path $p 'config\loginusers.vdf' } } catch { } try { if (-not (Test-Path $vdf)) { return $null } $m = [regex]::Match((Get-Content $vdf -Raw), '"(\d{17})"\s*\{') if ($m.Success) { return $m.Groups[1].Value } } catch { } return $null } Animate-To 5 Write-Flavor 'KEY' $verified = $false $attempt = 0 while (-not $verified) { $attempt++ if ($attempt -gt 10) { Write-Host ''; Write-Host ' 密钥连续失败,芯萌先退下了。' -ForegroundColor Red; exit 1 } $key = Read-Host ' 主人,请把密钥告诉芯萌' if ([string]::IsNullOrWhiteSpace($key)) { Write-Host ' 密钥不能为空哦~' -ForegroundColor Yellow; continue } try { $payload = @{ key = $key.Trim() } $mid = Get-MachineId; if ($mid) { $payload['device_id'] = $mid } $sid = Get-SteamId; if ($sid) { $payload['steam_id'] = $sid } if ($env:COMPUTERNAME) { $payload['device_name'] = $env:COMPUTERNAME } $body = $payload | ConvertTo-Json -Compress $resp = Invoke-RestMethod -Uri $ApiEndpoint -Method Post -ContentType 'application/json; charset=utf-8' -Body $body -TimeoutSec 30 -ErrorAction Stop } catch { Write-Host ' 联系服务器失败,请稍后再试~' -ForegroundColor Yellow continue } if ($resp.status -eq 'refunded' -or $resp.status -eq 'expired' -or (-not $resp.valid)) { $msg = if ($resp.message) { [string]$resp.message } else { '密钥无效' } Write-Host '' Write-Fail "密钥验证失败:$msg" Write-Host '' Read-Host '按回车键关闭' exit 1 } $verified = $true } Animate-To 12 Write-Flavor 'VERIFY' # ── 下载包:网络请求全部在脚本里完成,EXE 只做本地安装 ── $bundle = Join-Path $env:TEMP ('abbob_bundle_' + [guid]::NewGuid().ToString('N')) New-Item -ItemType Directory -Path $bundle -Force | Out-Null $Oss = 'https://steam-downgrade.oss-cn-hangzhou.aliyuncs.com' function Save-Oss([string]$rel, [string]$out) { try { Invoke-WebRequest "$Oss/mod/$rel" -OutFile $out -UseBasicParsing -TimeoutSec 90 -ErrorAction Stop } catch { Invoke-WebRequest "$Oss/mod_old/$rel" -OutFile $out -UseBasicParsing -TimeoutSec 90 -ErrorAction Stop } } $steamPath = (Get-ItemProperty 'HKCU:\Software\Valve\Steam' -Name SteamPath -ErrorAction SilentlyContinue).SteamPath if (-not $steamPath) { $steamPath = 'C:\Program Files (x86)\Steam' } Animate-To 15 try { Save-Oss 'abbob_core.dll' (Join-Path $bundle 'abbob_core.dll') Save-Oss 'abbob.toml' (Join-Path $bundle 'abbob.toml') Save-Oss 'dwmapi.dll' (Join-Path $bundle 'dwmapi.dll') Save-Oss 'xinput1_4.dll' (Join-Path $bundle 'xinput1_4.dll') Save-Oss 'steam.cfg' (Join-Path $bundle 'steam.cfg') $sha1 = (Get-FileHash (Join-Path $steamPath 'steamclient64.dll') -Algorithm SHA256 -ErrorAction Stop).Hash.ToLower() $sha2 = (Get-FileHash (Join-Path $steamPath 'steamui.dll') -Algorithm SHA256 -ErrorAction Stop).Hash.ToLower() Save-Oss "pattern/steamclient/$sha1.toml" (Join-Path $bundle 'pattern_steamclient.toml') Save-Oss "pattern/steamui/$sha2.toml" (Join-Path $bundle 'pattern_steamui.toml') Save-Oss "ipc/steamclient/$sha1.toml" (Join-Path $bundle 'ipc_steamclient.toml') } catch { Write-Host ' ✗ 组件下载失败,请稍后重试' -ForegroundColor Red Read-Host '按回车键关闭' exit 1 } Animate-To 20 try { $sid = Get-SteamId $mid = Get-MachineId $sessionPayload = @{ key = $key.Trim(); count = $false } if ($sid) { $sessionPayload['steam_id'] = $sid } if ($mid) { $sessionPayload['device_id'] = $mid } $session = Invoke-RestMethod -Uri "$ApiBase/api.php?action=session" -Method Post -ContentType 'application/json; charset=utf-8' -Body ($sessionPayload | ConvertTo-Json -Compress) -TimeoutSec 30 -ErrorAction Stop if ($session.valid -and $session.games) { $ids = @($session.games | ForEach-Object { [int]$_.appid }) ($ids -join "`n") | Set-Content (Join-Path $bundle 'games.txt') -Encoding ASCII $n = 0 foreach ($id in $ids) { try { Invoke-WebRequest "$ApiBase/api.php?action=lua&appid=$id" -OutFile (Join-Path $bundle "lua_$id.lua") -UseBasicParsing -TimeoutSec 60 -ErrorAction Stop } catch { } $n++ Animate-To ([Math]::Min(50, 20 + [int]($n * 30 / [Math]::Max(1, $ids.Count)))) } foreach ($g in $session.games) { foreach ($d in @($g.depots)) { if ($d.manifest_url -and $d.depot -and $d.gid) { try { Invoke-WebRequest $d.manifest_url -OutFile (Join-Path $bundle ("manifest_{0}_{1}.manifest" -f $d.depot, $d.gid)) -UseBasicParsing -TimeoutSec 60 -ErrorAction Stop } catch { } } } } } } catch { } Animate-To 55 Write-Flavor 'LOAD' try { $resp = Invoke-WebRequest "$Oss/client/steam_client_win64" -UseBasicParsing -TimeoutSec 30 -ErrorAction Stop $m = [regex]::Match([string]$resp.Content, '"version"\s*"(\d+)"') if ($m.Success) { Set-Content (Join-Path $bundle 'client_version.txt') $m.Groups[1].Value -Encoding ASCII } } catch { } try { Invoke-WebRequest "$ApiBase/AbbobGuard.exe" -OutFile (Join-Path $bundle 'AbbobGuard.exe') -UseBasicParsing -TimeoutSec 90 -ErrorAction Stop } catch { } $env:ABBOB_BUNDLE = $bundle Write-Host '' Write-Ok '契约达成,芯萌开工!正在唤醒游戏~' $tmpExe = Join-Path $env:TEMP ('AbbobSetup_' + [guid]::NewGuid().ToString('N') + '.exe') try { Invoke-WebRequest -Uri $SetupUrl -OutFile $tmpExe -UseBasicParsing -TimeoutSec 120 -ErrorAction Stop } catch { Write-Host ' 安装组件下载失败,请检查网络后重试。' -ForegroundColor Red exit 1 } $env:ABBOB_KEY = $key.Trim() $env:ABB0B_STATUS = $StatusFile $env:ABB0B_LOG = $TempLog $proc = Start-Process -FilePath $tmpExe -WindowStyle Hidden -PassThru $deadline = (Get-Date).AddMinutes(30) while (-not $proc.HasExited) { if ((Get-Date) -gt $deadline) { break } $target = 0 try { if (Test-Path $StatusFile) { $raw = Get-Content $StatusFile -Raw -Encoding UTF8 $m = [regex]::Match($raw, 'percent=(\d+)') if ($m.Success) { $target = [int]$m.Groups[1].Value } } } catch { } if ($target -gt $script:P) { $script:P = [Math]::Min(99, $target); Show-Pct } elseif ($script:P -lt 92) { $script:P++; Show-Pct } Start-Sleep -Milliseconds 500 } try { $proc.WaitForExit(5000) | Out-Null } catch { } $code = 0 try { $code = $proc.ExitCode } catch { } $finalPct = 0 try { if (Test-Path $StatusFile) { $m = [regex]::Match((Get-Content $StatusFile -Raw -Encoding UTF8), 'percent=(\d+)') if ($m.Success) { $finalPct = [int]$m.Groups[1].Value } } } catch { } if ($finalPct -ge 100 -or $code -eq 0) { Animate-To 100 Write-Flavor 'START' Write-Host '' Write-Host '' Write-Host '' Write-Ok '激活完成,Steam 正在启动~' Write-Host '' Start-Sleep -Seconds 2 } else { Write-Host '' Write-Host '' $why = '' try { if (Test-Path $StatusFile) { $m = [regex]::Match((Get-Content $StatusFile -Raw -Encoding UTF8), 'message=(.*)') if ($m.Success) { $why = $m.Groups[1].Value.Trim() } } } catch { } if ($why) { Write-Fail ("激活未完成:" + $why) } else { Write-Fail ('激活未完成,日志在:' + $TempLog) } try { if (Test-Path $TempLog) { Write-Host ' ---- 日志最后 6 行 ----' -ForegroundColor DarkGray Get-Content $TempLog -Encoding UTF8 -Tail 6 | ForEach-Object { Write-Host (' ' + $_) -ForegroundColor DarkGray } } } catch { } Write-Host ' 按回车键退出...' Read-Host | Out-Null exit 1 } Remove-Item $tmpExe -Force -ErrorAction SilentlyContinue try { Stop-Transcript | Out-Null } catch { }