$ErrorActionPreference = 'Continue' $testLog = 'C:\Apache24\htdocs\.codex_tmp\airmax_proton_cycle_test.log' $phpExe = 'C:\php\php.exe' $projectRoot = 'C:\Apache24\htdocs\mikrotik' $protonClient = 'C:\Program Files\Proton\VPN\v5.1.5\ProtonVPN.Client.exe' $protonDirectory = Split-Path -Parent $protonClient function Write-TestLog([string]$message) { $line = ('{0} {1}' -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss.fff'), $message) Add-Content -LiteralPath $testLog -Value $line -Encoding UTF8 } function Route-Snapshot([string]$label) { $routes = Get-NetRoute -AddressFamily IPv4 -ErrorAction SilentlyContinue | Where-Object { $_.DestinationPrefix -in @('0.0.0.0/0', '10.30.99.0/24') } | ForEach-Object { '{0}>{1}@{2} metric={3}' -f $_.DestinationPrefix, $_.NextHop, $_.InterfaceAlias, $_.RouteMetric } Write-TestLog ("ROUTES $label " + ($routes -join ' || ')) } Set-Content -LiteralPath $testLog -Value '' -Encoding UTF8 Write-TestLog 'BEGIN controlled Proton cycle' Route-Snapshot 'before-stop' try { Write-TestLog 'Stopping Proton client' Get-Process -Name 'ProtonVPN.Client' -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue Start-Sleep -Milliseconds 750 Write-TestLog 'Stopping Proton service' Stop-Service -Name 'ProtonVPN Service' -Force -ErrorAction Continue for ($attempt = 1; $attempt -le 12; $attempt++) { Start-Sleep -Seconds 1 $service = Get-Service -Name 'ProtonVPN Service' -ErrorAction SilentlyContinue $protonDefault = Get-NetRoute -InterfaceAlias 'ProTUN' -DestinationPrefix '0.0.0.0/0' -ErrorAction SilentlyContinue Write-TestLog ("WAIT attempt=$attempt service=$($service.Status) proton_default=$([bool]$protonDefault)") if ($service.Status -eq 'Stopped' -and -not $protonDefault) { break } } Route-Snapshot 'after-stop' $gatewayPing = Test-Connection -ComputerName '10.30.98.51' -Count 1 -Quiet -ErrorAction SilentlyContinue $devicePing = Test-Connection -ComputerName '10.30.99.25' -Count 1 -Quiet -ErrorAction SilentlyContinue Write-TestLog "PING gateway=$gatewayPing device=$devicePing" foreach ($url in @('http://10.30.99.25/', 'https://10.30.99.25/')) { $curlResult = & curl.exe -k -I --connect-timeout 3 --max-time 6 $url 2>&1 Write-TestLog ("CURL $url exit=$LASTEXITCODE " + (($curlResult | Select-Object -First 4) -join ' | ')) } $phpCode = @' require 'C:/Apache24/htdocs/mikrotik/includes/db.php'; require_once 'C:/Apache24/htdocs/mikrotik/admin/airmax_monitor_lib.php'; $out = airmax_probe_and_persist($conn, 27); echo json_encode([ 'ok' => $out['ok'] ?? false, 'status' => $out['status'] ?? '', 'message' => $out['message'] ?? '', 'route' => $out['route']['display'] ?? '', 'transport_blocked' => $out['transport_blocked'] ?? false, 'attempts' => count($out['probe']['attempts'] ?? []) ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); '@ $probeResult = & $phpExe -r $phpCode 2>&1 Write-TestLog ("PHP_PROBE exit=$LASTEXITCODE " + ($probeResult -join ' | ')) } catch { Write-TestLog ("ERROR " + $_.Exception.Message) } finally { Write-TestLog 'Starting Proton service' Start-Service -Name 'ProtonVPN Service' -ErrorAction Continue Start-Sleep -Seconds 2 Write-TestLog 'Starting Proton client' if (Test-Path -LiteralPath $protonClient) { Start-Process -FilePath $protonClient -WorkingDirectory $protonDirectory -WindowStyle Hidden } Start-Sleep -Seconds 12 $finalService = Get-Service -Name 'ProtonVPN Service' -ErrorAction SilentlyContinue $finalClient = Get-Process -Name 'ProtonVPN.Client' -ErrorAction SilentlyContinue Write-TestLog "RESTORED service=$($finalService.Status) client=$([bool]$finalClient)" Route-Snapshot 'after-restore' Write-TestLog 'END controlled Proton cycle' }