# Refresh the target's compositor before reading its accessibility tree and pixels. # Chromium can suspend page painting while fully covered. PrintWindow alone can # then return an old but otherwise valid bitmap. Do not activate or resize windows. function Build-Snapshot([string]$query, $TextLimit = $script:DefaultTextLimit, [int]$MaxTreeNodes = $script:AccessibilityTreeMaxNodeCount, [int]$MaxTreeDepth = $script:AccessibilityTreeMaxDepth) { $process = Resolve-App $query $hwnd = [IntPtr]$process.MainWindowHandle $wasTopmost = ([OCUWin32]::GetWindowLong($hwnd, -20) -band 8) -ne 0 $previous = [OCUWin32]::GetWindow($hwnd, 3) $raised = $false try { if ($null -ne (Get-CapturableWindowFrame $hwnd)) { # NOMOVE | NOSIZE | NOACTIVATE | NOOWNERZORDER. This may briefly expose # the authorized target, but never focuses or captures another window. $raised = [OCUWin32]::SetWindowPos($hwnd, [IntPtr](-1), 0, 0, 0, 0, 0x213) if ($raised) { Start-Sleep -Milliseconds 300 [void][OCUWin32]::DwmFlush() } } $element = Get-MainElement $process $bounds = Get-WindowBounds $process $element $rendered = Render-Tree $element $bounds $TextLimit $MaxTreeNodes $MaxTreeDepth $image = if ($raised) { Capture-WindowPngBase64 $bounds $hwnd } else { $null } [pscustomobject]@{ app = [pscustomobject]@{ name=$process.ProcessName; bundleIdentifier=$process.ProcessName; pid=[int]$process.Id } windowTitle = Limit-Text $process.MainWindowTitle $TextLimit windowBounds = $bounds screenshotPngBase64 = $image treeLines = @($rendered.lines) focusedSummary = Get-FocusedSummary $process.Id $TextLimit selectedText = Get-SelectedText $process.Id $TextLimit elements = @($rendered.records) } } finally { if ($raised) { if (-not $wasTopmost) { [void][OCUWin32]::SetWindowPos($hwnd, [IntPtr](-2), 0, 0, 0, 0, 0x213) } if ($previous -ne [IntPtr]::Zero -and [OCUWin32]::IsWindow($previous)) { [void][OCUWin32]::SetWindowPos($hwnd, $previous, 0, 0, 0, 0, 0x213) } } } }