# WebView2 CDP (Chrome DevTools Protocol) E2E helper. # Usage: . .\scripts\cdp.ps1; Invoke-Cdp "document.title" # Prereq: app launched with WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS=--remote-debugging-port=9223 # NOTE: ASCII only in this file (PS 5.1 reads BOM-less files as ANSI). function Invoke-Cdp { param( [Parameter(Mandatory)] [string]$Expression, [int]$Port = 9223, [int]$TimeoutSec = 20 ) $targets = Invoke-RestMethod "http://127.0.0.1:$Port/json" $page = $targets | Where-Object { $_.type -eq 'page' -and $_.url -notlike 'devtools*' } | Select-Object -First 1 if (-not $page) { throw "no CDP page target" } $ws = New-Object System.Net.WebSockets.ClientWebSocket $ct = [System.Threading.CancellationToken]::None $uri = [Uri]$page.webSocketDebuggerUrl $ws.ConnectAsync($uri, $ct).GetAwaiter().GetResult() | Out-Null $msg = @{ id = 1 method = "Runtime.evaluate" params = @{ expression = $Expression returnByValue = $true awaitPromise = $true } } | ConvertTo-Json -Depth 6 -Compress $bytes = [System.Text.Encoding]::UTF8.GetBytes($msg) $seg = New-Object System.ArraySegment[byte] -ArgumentList @(,$bytes) $ws.SendAsync($seg, [System.Net.WebSockets.WebSocketMessageType]::Text, $true, $ct).GetAwaiter().GetResult() | Out-Null $buffer = New-Object byte[] 1048576 $deadline = (Get-Date).AddSeconds($TimeoutSec) $response = $null while ((Get-Date) -lt $deadline) { $sb = New-Object System.Text.StringBuilder do { $rseg = New-Object System.ArraySegment[byte] -ArgumentList @(,$buffer) $result = $ws.ReceiveAsync($rseg, $ct).GetAwaiter().GetResult() $sb.Append([System.Text.Encoding]::UTF8.GetString($buffer, 0, $result.Count)) | Out-Null } while (-not $result.EndOfMessage) $obj = $sb.ToString() | ConvertFrom-Json if ($obj.id -eq 1) { $response = $obj; break } } $ws.Abort() if (-not $response) { throw "CDP response timeout" } if ($response.result.exceptionDetails) { throw "JS exception: $($response.result.exceptionDetails.text) $($response.result.exceptionDetails.exception.description)" } return $response.result.result.value }