feat(diagnostic): 完成阶段 0B 原生键盘隔离消费探测
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
param(
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Path
|
||||
)
|
||||
@@ -39,7 +39,183 @@ $textLeaks = @($records | Where-Object {
|
||||
$_.messageCategory -eq 'text' -and $_.wParamHex -ne $null
|
||||
})
|
||||
$lost = @($records | Where-Object recordType -eq 'records_lost')
|
||||
$lostTotal = 0
|
||||
foreach ($lostRecord in $lost) {
|
||||
if ($null -ne $lostRecord.lostCount) {
|
||||
$lostTotal += [int]$lostRecord.lostCount
|
||||
}
|
||||
else {
|
||||
$lostTotal++
|
||||
}
|
||||
}
|
||||
$attach = $records | Where-Object recordType -eq 'window_attach' | Select-Object -First 1
|
||||
$closeObserved = @($records | Where-Object messageName -eq 'WM_CLOSE').Count -gt 0
|
||||
$sessionEndObserved = @($records | Where-Object recordType -eq 'session_end').Count -gt 0
|
||||
$experimentConfigs = @($records | Where-Object recordType -eq 'experiment_config')
|
||||
if ($experimentConfigs.Count -gt 1) {
|
||||
throw "More than one experiment_config record was found: $($experimentConfigs.Count)"
|
||||
}
|
||||
$experimentConfig = $experimentConfigs | Select-Object -First 1
|
||||
$experimentTargetEnters = @()
|
||||
$experimentTargetLeaves = @()
|
||||
$experimentEnters = @()
|
||||
$experimentLeaves = @()
|
||||
$matchingEasyX = @()
|
||||
$easyxVisibility = $null
|
||||
$experimentValidity = 'not_configured'
|
||||
$imePositionAttempts = @()
|
||||
$imePositionSuccesses = @()
|
||||
$imePositionResultRecords = @()
|
||||
$imePositionOrphans = @()
|
||||
$runtimeFailOpenEnters = @()
|
||||
$runtimeFailOpenLeaves = @()
|
||||
$runtimeFailOpenReason = $null
|
||||
if ($experimentConfig) {
|
||||
$schemaVersions = @($records | Select-Object -ExpandProperty schemaVersion -Unique)
|
||||
$experimentTargetEnters = @($records | Where-Object {
|
||||
$_.recordType -eq 'wndproc_enter' -and
|
||||
$_.experimentId -eq $experimentConfig.experimentId -and
|
||||
$_.ruleId -eq $experimentConfig.ruleId
|
||||
})
|
||||
$targetCallIds = @($experimentTargetEnters | Select-Object -ExpandProperty wndProcCallId)
|
||||
$experimentTargetLeaves = @($records | Where-Object {
|
||||
$_.recordType -eq 'wndproc_leave' -and
|
||||
$targetCallIds -contains $_.wndProcCallId
|
||||
})
|
||||
$runtimeFailOpenEnters = @($experimentTargetEnters | Where-Object failOpenApplied -eq $true)
|
||||
$runtimeFailOpenCallIds = @($runtimeFailOpenEnters | Select-Object -ExpandProperty wndProcCallId)
|
||||
$runtimeFailOpenLeaves = @($experimentTargetLeaves | Where-Object {
|
||||
$runtimeFailOpenCallIds -contains $_.wndProcCallId -and $_.failOpenApplied -eq $true
|
||||
})
|
||||
$runtimeFailOpenRecords = @($runtimeFailOpenEnters) + @($runtimeFailOpenLeaves)
|
||||
$runtimeFailOpenReasons = @($runtimeFailOpenRecords |
|
||||
Select-Object -ExpandProperty failOpenReason -Unique)
|
||||
if ($runtimeFailOpenReasons.Count -eq 1) {
|
||||
$runtimeFailOpenReason = [string]$runtimeFailOpenReasons[0]
|
||||
}
|
||||
$experimentEnters = @($experimentTargetEnters | Where-Object ruleMatched -eq $true)
|
||||
$matchedCallIds = @($experimentEnters | Select-Object -ExpandProperty wndProcCallId)
|
||||
$experimentLeaves = @($records | Where-Object {
|
||||
$_.recordType -eq 'wndproc_leave' -and
|
||||
$matchedCallIds -contains $_.wndProcCallId
|
||||
})
|
||||
$easyXMessageType = if ([string]$experimentConfig.targetMessage -match 'UP$') {
|
||||
'WM_KEYUP'
|
||||
}
|
||||
else {
|
||||
'WM_KEYDOWN'
|
||||
}
|
||||
$targetScanSpecified = $null -ne $experimentConfig.targetScanCode
|
||||
$matchingEasyX = @($records | Where-Object {
|
||||
$_.recordType -eq 'easyx_key' -and
|
||||
$_.easyxMessageType -eq $easyXMessageType -and
|
||||
[int]$_.easyxVkCode -eq [int]$experimentConfig.targetVirtualKey -and
|
||||
(-not $targetScanSpecified -or
|
||||
[int]$_.easyxScanCode -eq [int]$experimentConfig.targetScanCode)
|
||||
})
|
||||
$imePositionResultRecords = @($records | Where-Object recordType -eq 'ime_position')
|
||||
# 兼容本修复前把定位结果直接挂在 wndproc_enter 上的 schema v2 日志。
|
||||
$legacyImePositionAttempts = @($records | Where-Object {
|
||||
$_.recordType -eq 'wndproc_enter' -and $_.imePositionAttempted -eq $true
|
||||
})
|
||||
$imePositionAttempts = @($imePositionResultRecords) + @($legacyImePositionAttempts)
|
||||
$imePositionSuccesses = @($imePositionAttempts | Where-Object {
|
||||
$_.imePositionContextAvailable -eq $true -and
|
||||
$_.compositionPositionSucceeded -eq $true -and
|
||||
$_.candidatePositionSucceeded -eq $true
|
||||
})
|
||||
$sequenceLookup = @{}
|
||||
foreach ($entry in $records) { $sequenceLookup[[string]$entry.sequence] = $true }
|
||||
$imePositionOrphans = @($imePositionResultRecords | Where-Object {
|
||||
$null -eq $_.parentSequence -or
|
||||
-not $sequenceLookup.ContainsKey([string]$_.parentSequence) -or
|
||||
[uint64]$_.parentSequence -ge [uint64]$_.sequence
|
||||
})
|
||||
$easyxVisibility = if ($matchingEasyX.Count -eq 0) {
|
||||
'absent'
|
||||
}
|
||||
elseif ($matchingEasyX.Count -eq 1) {
|
||||
'present_once'
|
||||
}
|
||||
else {
|
||||
'present_multiple'
|
||||
}
|
||||
|
||||
if ($schemaVersions.Count -ne 1 -or [int]$schemaVersions[0] -ne 2) {
|
||||
$experimentValidity = 'invalid_schema'
|
||||
}
|
||||
elseif (-not $sequenceStrict) {
|
||||
$experimentValidity = 'inconclusive_sequence'
|
||||
}
|
||||
elseif ($textLeaks.Count -gt 0) {
|
||||
$experimentValidity = 'inconclusive_text_leak'
|
||||
}
|
||||
elseif ($lostTotal -gt 0) {
|
||||
$experimentValidity = 'inconclusive_capture_loss'
|
||||
}
|
||||
elseif ($imePositionOrphans.Count -gt 0) {
|
||||
$experimentValidity = 'inconclusive_ime_position_link'
|
||||
}
|
||||
elseif (-not $closeObserved) {
|
||||
$experimentValidity = 'inconclusive_close_missing'
|
||||
}
|
||||
elseif (-not $sessionEndObserved) {
|
||||
$experimentValidity = 'inconclusive_session_end_missing'
|
||||
}
|
||||
elseif (-not $experimentConfig.configurationValid) {
|
||||
$experimentValidity = 'invalid_configuration'
|
||||
}
|
||||
elseif (-not $experimentConfig.ruleEligible) {
|
||||
$experimentValidity = 'ineligible_fail_open'
|
||||
}
|
||||
elseif ([string]$experimentConfig.inputSource -eq 'Manual' -and
|
||||
(-not $experimentConfig.imePositionConfigured -or $imePositionSuccesses.Count -eq 0)) {
|
||||
$experimentValidity = 'inconclusive_ime_position'
|
||||
}
|
||||
elseif ($experimentTargetEnters.Count -ne [int]$experimentConfig.maxMatches) {
|
||||
$experimentValidity = 'unexpected_target_count'
|
||||
}
|
||||
elseif ([string]$experimentConfig.requestedAction -eq 'ObserveAndConsume' -and
|
||||
$experimentEnters.Count -eq 0 -and
|
||||
$runtimeFailOpenEnters.Count -eq [int]$experimentConfig.maxMatches -and
|
||||
$runtimeFailOpenLeaves.Count -eq $runtimeFailOpenEnters.Count -and
|
||||
$runtimeFailOpenReasons.Count -eq 1 -and
|
||||
-not [string]::IsNullOrWhiteSpace($runtimeFailOpenReason) -and
|
||||
@($runtimeFailOpenLeaves | Where-Object {
|
||||
$_.actualAction -ne 'ObserveAndForward' -or $_.forwarded -ne $true
|
||||
}).Count -eq 0) {
|
||||
$experimentValidity = 'runtime_fail_open'
|
||||
}
|
||||
elseif ($experimentEnters.Count -ne [int]$experimentConfig.maxMatches) {
|
||||
$experimentValidity = 'unexpected_match_count'
|
||||
}
|
||||
elseif ($experimentLeaves.Count -ne $experimentEnters.Count) {
|
||||
$experimentValidity = 'missing_leave_record'
|
||||
}
|
||||
elseif ([string]$experimentConfig.requestedAction -eq 'ObserveAndConsume' -and
|
||||
@($experimentLeaves | Where-Object actualAction -ne 'ObserveAndConsume').Count -gt 0) {
|
||||
$experimentValidity = 'consume_action_mismatch'
|
||||
}
|
||||
elseif ([string]$experimentConfig.requestedAction -eq 'ObserveAndConsume' -and
|
||||
@($experimentLeaves | Where-Object forwarded -eq $true).Count -gt 0) {
|
||||
$experimentValidity = 'consume_was_forwarded'
|
||||
}
|
||||
elseif ([string]$experimentConfig.requestedAction -eq 'ObserveAndConsume' -and
|
||||
@($experimentLeaves | Where-Object forwardResultHex -ne '0x0000000000000000').Count -gt 0) {
|
||||
$experimentValidity = 'consume_result_nonzero'
|
||||
}
|
||||
elseif ([string]$experimentConfig.requestedAction -eq 'ObserveAndForward' -and
|
||||
@($experimentLeaves | Where-Object actualAction -ne 'ObserveAndForward').Count -gt 0) {
|
||||
$experimentValidity = 'forward_action_mismatch'
|
||||
}
|
||||
elseif ([string]$experimentConfig.requestedAction -eq 'ObserveAndForward' -and
|
||||
@($experimentLeaves | Where-Object forwarded -ne $true).Count -gt 0) {
|
||||
$experimentValidity = 'forward_was_not_forwarded'
|
||||
}
|
||||
else {
|
||||
$experimentValidity = 'valid'
|
||||
}
|
||||
}
|
||||
|
||||
$correlationCounts = [ordered]@{}
|
||||
foreach ($entry in $echoSummaries) {
|
||||
@@ -51,8 +227,10 @@ foreach ($entry in $echoSummaries) {
|
||||
[pscustomobject]@{
|
||||
file = $file.FullName
|
||||
recordCount = $records.Count
|
||||
schemaVersions = @($records | Select-Object -ExpandProperty schemaVersion -Unique)
|
||||
sequenceStrict = $sequenceStrict
|
||||
recordsLost = $lost.Count
|
||||
recordsLost = $lostTotal
|
||||
lossRecordCount = $lost.Count
|
||||
textRawWParamLeaks = $textLeaks.Count
|
||||
isWindowUnicode = $attach.isWindowUnicode
|
||||
ansiCodePage = $attach.ansiCodePage
|
||||
@@ -72,6 +250,34 @@ foreach ($entry in $echoSummaries) {
|
||||
successfulScalarCounts = @($successfulResults | Select-Object -ExpandProperty scalarCount)
|
||||
digestPresentCount = @($successfulResults | Where-Object sessionDigest -ne $null).Count
|
||||
correlationCounts = [pscustomobject]$correlationCounts
|
||||
closeObserved = @($records | Where-Object messageName -eq 'WM_CLOSE').Count -gt 0
|
||||
sessionEndObserved = @($records | Where-Object recordType -eq 'session_end').Count -gt 0
|
||||
closeObserved = $closeObserved
|
||||
sessionEndObserved = $sessionEndObserved
|
||||
experimentConfigured = $null -ne $experimentConfig
|
||||
experimentId = if ($experimentConfig) { $experimentConfig.experimentId } else { $null }
|
||||
ruleId = if ($experimentConfig) { $experimentConfig.ruleId } else { $null }
|
||||
ruleEligible = if ($experimentConfig) { [bool]$experimentConfig.ruleEligible } else { $null }
|
||||
experimentFailOpenReason = if ($experimentConfig) { $experimentConfig.failOpenReason } else { $null }
|
||||
runtimeFailOpenReason = $runtimeFailOpenReason
|
||||
requestedAction = if ($experimentConfig) { $experimentConfig.requestedAction } else { $null }
|
||||
targetMessage = if ($experimentConfig) { $experimentConfig.targetMessage } else { $null }
|
||||
targetVirtualKey = if ($experimentConfig) { $experimentConfig.targetVirtualKey } else { $null }
|
||||
targetScanCode = if ($experimentConfig) { $experimentConfig.targetScanCode } else { $null }
|
||||
baselineId = if ($experimentConfig) { $experimentConfig.baselineId } else { $null }
|
||||
targetObservationCount = $experimentTargetEnters.Count
|
||||
targetLeaveCount = $experimentTargetLeaves.Count
|
||||
failOpenObservationCount = @($experimentTargetEnters | Where-Object failOpenApplied -eq $true).Count
|
||||
failOpenForwardedCount = @($experimentTargetLeaves | Where-Object {
|
||||
$_.failOpenApplied -eq $true -and $_.forwarded -eq $true
|
||||
}).Count
|
||||
ruleMatchCount = $experimentEnters.Count
|
||||
consumedMatchCount = @($experimentEnters | Where-Object actualAction -eq 'ObserveAndConsume').Count
|
||||
forwardedMatchCount = @($experimentLeaves | Where-Object forwarded -eq $true).Count
|
||||
matchingEasyXKeyCount = $matchingEasyX.Count
|
||||
easyxVisibility = $easyxVisibility
|
||||
imePositionAttemptCount = $imePositionAttempts.Count
|
||||
imePositionSuccessCount = $imePositionSuccesses.Count
|
||||
imePositionReady = $imePositionSuccesses.Count -gt 0
|
||||
imePositionResultRecordCount = $imePositionResultRecords.Count
|
||||
imePositionOrphanCount = $imePositionOrphans.Count
|
||||
experimentValidity = $experimentValidity
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user