4da5287d01
Execute HCAL roadmap R1.2 (GetRuntimeParameterAsync) end-to-end, and in doing so
discover that the "string-handle wall" blocking R1.1/R1.4/R1.5/R1.6 was a handle
FORMAT bug, not a missing native session/filter registration.
R1.2 (shipped, live-verified):
- Captured native GetRuntimeParameter -> WCF op aa/Stat/GETRP (string-handle op,
GETHI's shape), via scripts/Capture-RuntimeParam.ps1 + instrument-wcf-{write,read}message.
- HistorianRuntimeParameterProtocol serializes pRequestBuff (54 67 01 00 + uint
nameCount + per-name uint charCount + UTF-16) and parses pResponseBuff (version +
uint resultCount + CRetVariant 0x43 VT_BSTR + uint16 len + uint16 charCount + UTF-16).
- IStatusServiceContract2.GetRuntimeParameter (GETRP) op; HistorianWcfStatusClient
passes the Open2 storage-session GUID as the string handle, UPPERCASE.
- Public HistorianClient.GetRuntimeParameterAsync(name) via the dialect.
- Golden WcfRuntimeParameterProtocolTests + gated live test; returns HistorianVersion.
String-handle wall RESOLVED (proven, public APIs deferred):
- The Open2 storage GUID works as the string handle when sent UPPERCASE
(ToString("D").ToUpperInvariant()); earlier "blocked" probes used lowercase.
- Live-probed GETHI (R1.4) -> returns data; ExeC (R1.1) -> Retr.GetV prime -> ExeC ->
GetR returns a BinaryFormatter-serialized .NET DataTable. Gated
StringHandleProbeDiagnosticTests + scripts/Capture-ExecSql.ps1 + exec-sql harness scenario.
- Docs flipped: wcf-string-handle-wall.md RESOLVED banner; roadmap R1.1/R1.4 reachable,
R1.5/R1.6 likely; wcf-status-localhost.md GETRP section.
- R1.1/R1.4 public APIs NOT shipped: ExeC needs a GetR paging loop + a BinaryFormatter-
stream parser (BinaryFormatter is removed from .NET 10); GETHI full-info struct needs
its own capture.
223 unit tests pass; gated live tests green against the local 2020 Historian.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B6mcaT2PjRFKcogzp9UkfC
92 lines
4.3 KiB
PowerShell
92 lines
4.3 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Captures the native AVEVA client's ExecuteSqlCommand wire traffic (HCAL roadmap R1.1) so the
|
|
Retr.ExeC + Retr.GetR string-handle SQL surface (op names, handle format, command/option
|
|
encoding, Retr priming, GetR result byte stream) can be decoded instead of guessed.
|
|
|
|
.DESCRIPTION
|
|
Drives the .NET-Framework NativeTraceHarness `exec-sql` scenario against the live Historian
|
|
with an IL-rewritten copy of aahClientManaged.dll whose ClientMessageEncoder.WriteMessage AND
|
|
ReadMessage are instrumented to log every MDAS body. Read-only benign query.
|
|
|
|
.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,
|
|
[string]$Sql = "SELECT 1 AS ProbeValue",
|
|
[string]$SqlOption = "ExecuteRecord",
|
|
[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-exec-sql"
|
|
$currentCopy = Join-Path $captureDir "current-copy"
|
|
$instrDll = Join-Path $captureDir "aahClientManaged.dll"
|
|
$capturePath = Join-Path $captureDir "exec-sql-capture-latest.ndjson"
|
|
|
|
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 + ReadMessage ==" -ForegroundColor Cyan
|
|
New-Item -ItemType Directory -Force -Path $captureDir | Out-Null
|
|
$writeOnly = Join-Path $captureDir "aahClientManaged.write.dll"
|
|
dotnet run --no-build -c $Configuration --project $reProj -- `
|
|
instrument-wcf-writemessage (Join-Path $repoRoot "current\aahClientManaged.dll") $writeOnly | Out-Null
|
|
dotnet run --no-build -c $Configuration --project $reProj -- `
|
|
instrument-wcf-readmessage $writeOnly $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"
|
|
if (Test-Path $capturePath) { Remove-Item -Force $capturePath }
|
|
$env:AVEVA_HISTORIAN_RE_CAPTURE = $capturePath
|
|
|
|
Write-Host "== Capturing exec-sql ==" -ForegroundColor Green
|
|
$harnessArgs = @(
|
|
"--scenario", "exec-sql",
|
|
"--server-name", $ServerName,
|
|
"--tcp-port", "$TcpPort",
|
|
"--sql", $Sql,
|
|
"--sql-option", $SqlOption,
|
|
"--current-dir", $currentCopy,
|
|
"--managed-dll-path", $harnessDll
|
|
)
|
|
|
|
$harnessJson = $null
|
|
try {
|
|
$prevEap = $ErrorActionPreference
|
|
$ErrorActionPreference = "Continue"
|
|
$harnessJson = & dotnet run --no-build -c $Configuration --project $harnessProj -- @harnessArgs 2>&1
|
|
} catch {
|
|
Write-Host " (exec-sql raised: $($_.Exception.Message))" -ForegroundColor Yellow
|
|
} finally {
|
|
$ErrorActionPreference = $prevEap
|
|
}
|
|
|
|
Remove-Item Env:\AVEVA_HISTORIAN_RE_CAPTURE -ErrorAction SilentlyContinue
|
|
|
|
$recCount = if (Test-Path $capturePath) { (Get-Content $capturePath | Where-Object { $_.Trim() }).Count } else { 0 }
|
|
Write-Host "`n== Capture summary ==" -ForegroundColor Cyan
|
|
Write-Host " -> $recCount records -> $capturePath"
|
|
$harnessJson | Select-Object -Last 6
|