# ============================================================ # DouParse proxy agent bootstrap (public: /assets/agent-bootstrap.ps1) # ASCII-only on purpose: Windows PowerShell 5.1 reads BOM-less UTF-8 as # ANSI/GBK and mangles Chinese bytes into syntax errors. Keep it ASCII. # Usage (target machine): # curl.exe -o bootstrap.ps1 https://www.qiaiwan.top/assets/agent-bootstrap.ps1 # powershell -ExecutionPolicy Bypass -File .\bootstrap.ps1 # Does: place agent -> install Python/deps -> write autostart VBS -> launch # ============================================================ $ErrorActionPreference = 'Stop' $dir = Join-Path $env:USERPROFILE 'douparse-agent' New-Item -ItemType Directory -Force -Path $dir | Out-Null # 0) place proxy_agent.py: ALWAYS download the latest from server first # (update-safe since 2026-08-13: an old local copy in home/cwd must NOT # shadow the new version; local files are fallback only when download # fails). Cache-busting ?v= defeats any intermediate HTTP cache. $src = Join-Path $env:TEMP 'dp_proxy_agent.py' $dlOk = $false try { $ts = [DateTimeOffset]::UtcNow.ToUnixTimeSeconds() Write-Output '[bootstrap] downloading latest proxy_agent.py ...' Invoke-WebRequest -Uri ('https://www.qiaiwan.top/assets/proxy_agent.py?v=' + $ts) -OutFile $src -UseBasicParsing if ((Test-Path $src) -and ((Get-Item $src).Length -gt 1000)) { $dlOk = $true } } catch { Write-Output ('[bootstrap] download failed: ' + $_.Exception.Message) } if (-not $dlOk) { Write-Output '[bootstrap] falling back to local proxy_agent.py ...' $src = $null foreach ($c in @( (Join-Path $env:USERPROFILE 'proxy_agent.py'), (Join-Path $PSScriptRoot 'proxy_agent.py'), (Join-Path (Get-Location) 'proxy_agent.py') )) { if (Test-Path $c) { $src = $c; break } } if (-not $src) { throw 'no proxy_agent.py available (download failed and no local copy)' } } # print agent version so the operator can confirm the new build is in place $ver = Select-String -Path $src -Pattern 'AGENT_VERSION\s*=\s*"([^"]+)"' | Select-Object -First 1 if ($ver) { Write-Output ('[bootstrap] agent version: ' + $ver.Matches[0].Groups[1].Value) } Copy-Item $src (Join-Path $dir 'proxy_agent.py') -Force $agent = Join-Path $dir 'proxy_agent.py' # 1) resolve / install Python # NOTE: WindowsApps\python.exe is a Microsoft Store stub, must skip it function Resolve-Python { $p = Get-Command python -ErrorAction SilentlyContinue if ($p -and $p.Source -and ($p.Source -notlike '*\WindowsApps\*')) { return $p.Source } foreach ($c in @( (Join-Path $env:LOCALAPPDATA 'Programs\Python\Python312\python.exe'), (Join-Path $env:LOCALAPPDATA 'Programs\Python\Python313\python.exe'), (Join-Path $env:ProgramFiles 'Python312\python.exe') )) { if (Test-Path $c) { return $c } } return $null } $python = Resolve-Python if (-not $python) { Write-Output '[bootstrap] installing python 3.12 ...' $url = 'https://registry.npmmirror.com/-/binary/python/3.12.5/python-3.12.5-amd64.exe' $inst = Join-Path $env:TEMP 'python-installer.exe' Invoke-WebRequest -Uri $url -OutFile $inst -UseBasicParsing Start-Process -FilePath $inst -ArgumentList '/quiet', 'InstallAllUsers=0', 'PrependPath=1', 'Include_pip=1' -Wait Remove-Item $inst -Force -ErrorAction SilentlyContinue $python = Resolve-Python if (-not $python) { throw 'python install failed' } } Write-Output "[bootstrap] python: $python" # 2) deps (aliyun mirror) & $python -m pip install -i https://mirrors.aliyun.com/pypi/simple/ httpx websockets # 3) autostart VBS in Startup folder (pythonw = no console window) $pydir = Split-Path $python -Parent $pyw = Join-Path $pydir 'pythonw.exe' if (-not (Test-Path $pyw)) { $pyw = Join-Path $pydir 'python.exe' } $startup = [Environment]::GetFolderPath('Startup') $vbs = 'Set ws = CreateObject("WScript.Shell")' + "`r`n" + 'ws.Run """' + $pyw + '"" """' + $agent + '""", 0, False' Set-Content -Path (Join-Path $startup 'douparse_proxy_agent.vbs') -Value $vbs -Encoding ASCII Write-Output "[bootstrap] autostart vbs: $startup\douparse_proxy_agent.vbs" # 4) launch now (kill old agent first: single-instance lock would block the new one) try { $old = Get-CimInstance Win32_Process -Filter "Name='pythonw.exe' OR Name='python.exe'" | Where-Object { $_.CommandLine -like '*proxy_agent.py*' } if ($old) { Stop-Process -Id $old.ProcessId -Force -ErrorAction SilentlyContinue Start-Sleep -Seconds 2 } } catch { } if (-not $pyw -or -not (Test-Path $pyw)) { throw "pythonw not found near: $python" } Start-Process -FilePath $pyw -ArgumentList $agent -WindowStyle Hidden Write-Output '[bootstrap] agent launched. log: ' + (Join-Path $dir 'proxy_agent.log') Write-Output '[bootstrap] DONE'