<# .SYNOPSIS Captures the native client's StartEventQuery request bytes WITH and WITHOUT an event filter (HCAL roadmap R1.7) so the filter-predicate encoding can be decoded against the empty-filter baseline instead of guessed. .DESCRIPTION Drives the NativeTraceHarness `event` scenario against the live Historian under an IL-rewritten aahClientManaged.dll whose ClientMessageEncoder.WriteMessage is instrumented to log every outgoing MDAS body. Runs twice: - baseline : no filter (the known empty-filter StartEventQuery) - filtered : EventQuery.AddEventFilter("Area", Equal, "RetestFilterArea") before StartQuery Diff the two StartEventQuery request buffers (scripts/decode-event-filter-capture.py) to read off the exact filter-block bytes (property name / comparison op / value) the native client emits, then implement the managed predicate against that. .NOTES Artifacts are diagnostic and gitignored. Sanitize before copying into docs/. Never commit raw capture NDJSON, credentials, hostnames, or customer tag names. #> [CmdletBinding()] param( [string]$ServerName = "localhost", [int]$TcpPort = 32568, [int]$LookbackMinutes = 43200, # Property:Op:Value (Op = a HistorianComparisionType name, e.g. Equal/Contains/GreaterThan). [string]$Filter = "Area:Equal:RetestFilterArea", [string]$Configuration = "Debug" ) $ErrorActionPreference = "Stop" $repoRoot = Split-Path -Parent $PSScriptRoot Set-Location $repoRoot $reProj = Join-Path $repoRoot "tools\AVEVA.Historian.ReverseEngineering\AVEVA.Historian.ReverseEngineering.csproj" $harnessProj = Join-Path $repoRoot "tools\AVEVA.Historian.NativeTraceHarness\AVEVA.Historian.NativeTraceHarness.csproj" $instrProj = Join-Path $repoRoot "tools\AVEVA.Historian.ReverseInstrumentation\AVEVA.Historian.ReverseInstrumentation.csproj" $captureDir = Join-Path $repoRoot "artifacts\reverse-engineering\instrumented-wcf-event-filter" $currentCopy = Join-Path $captureDir "current-copy" $instrDll = Join-Path $captureDir "aahClientManaged.dll" Write-Host "== Building tooling ($Configuration) ==" -ForegroundColor Cyan dotnet build $reProj -c $Configuration --nologo -v q | Out-Null dotnet build $instrProj -c $Configuration --nologo -v q | Out-Null dotnet build $harnessProj -c $Configuration --nologo -v q | Out-Null $instrSourceDll = Get-ChildItem -Recurse (Join-Path $repoRoot "tools\AVEVA.Historian.ReverseInstrumentation\bin\$Configuration") ` -Filter "AVEVA.Historian.ReverseInstrumentation.dll" | Select-Object -First 1 -ExpandProperty FullName if (-not $instrSourceDll) { throw "ReverseInstrumentation.dll not found under bin\$Configuration." } Write-Host "== Instrumenting WriteMessage ==" -ForegroundColor Cyan New-Item -ItemType Directory -Force -Path $captureDir | Out-Null dotnet run --no-build -c $Configuration --project $reProj -- ` instrument-wcf-writemessage (Join-Path $repoRoot "current\aahClientManaged.dll") $instrDll | Out-Null Write-Host "== Staging current-copy ==" -ForegroundColor Cyan robocopy (Join-Path $repoRoot "current") $currentCopy /MIR /NJH /NJS /NDL /NP /NC /NS | Out-Null Copy-Item -Force $instrDll (Join-Path $currentCopy "aahClientManaged.dll") Copy-Item -Force $instrSourceDll (Join-Path $currentCopy "AVEVA.Historian.ReverseInstrumentation.dll") $harnessDll = Join-Path $currentCopy "aahClientManaged.dll" $matrix = @( @{ Name = "baseline"; Args = @() }, @{ Name = "filtered"; Args = @("--event-filter", $Filter) } ) foreach ($cfg in $matrix) { $capturePath = Join-Path $captureDir "event-filter-capture-$($cfg.Name)-latest.ndjson" if (Test-Path $capturePath) { Remove-Item -Force $capturePath } $env:AVEVA_HISTORIAN_RE_CAPTURE = $capturePath Write-Host "== Capturing: $($cfg.Name) ==" -ForegroundColor Green $harnessArgs = @( "--scenario", "event", "--server-name", $ServerName, "--tcp-port", "$TcpPort", "--lookback-minutes", "$LookbackMinutes", "--max-rows", "1", "--current-dir", $currentCopy, "--managed-dll-path", $harnessDll ) + $cfg.Args try { $prevEap = $ErrorActionPreference $ErrorActionPreference = "Continue" & dotnet run --no-build -c $Configuration --project $harnessProj -- @harnessArgs 2>&1 | Out-Null } catch { Write-Host " ($($cfg.Name) raised: $($_.Exception.Message))" -ForegroundColor Yellow } finally { $ErrorActionPreference = $prevEap } $recCount = if (Test-Path $capturePath) { (Get-Content $capturePath | Where-Object { $_.Trim() }).Count } else { 0 } Write-Host " -> $recCount records -> $capturePath" } Remove-Item Env:\AVEVA_HISTORIAN_RE_CAPTURE -ErrorAction SilentlyContinue Write-Host "`nDecode with: python scripts\decode-event-filter-capture.py" -ForegroundColor Cyan