Skip to content

Avoid re-resolving one-shot UI elements - #841

Merged
Zach Teutsch (zateutsch) merged 3 commits into
mainfrom
nmetulev-retain-resolved-ui-elements
Sep 16, 2026
Merged

Zach Teutsch (zateutsch) merged 3 commits into
mainfrom
nmetulev-retain-resolved-ui-elements

Conversation

@nmetulev

Copy link
Copy Markdown
Member

Fixes #840

Retains the live UI Automation provider element in an internal, non-serialized context on UiElement, allowing one-shot property, value, invoke, set-value, focus, scrolling, scoped inspection/capture, and element-window operations to reuse the element already found by selector resolution.

Serialized or externally constructed UiElement instances continue through the existing ResolveComElement fallback, and stale retained elements preserve the explicit stale-element error.

Deterministic instrumentation verifies:

  • freshly resolved elements perform 0 serialized/tree re-resolutions across all affected operations
  • a caller-provided serialized element performs exactly 1 fallback resolution

Validation:

  • 4 focused retained/stale/fallback regression tests passed
  • 116 RealUiAutomationTests passed
  • 556 UiCommandTests ran: 555 passed, 1 opt-in recording test skipped
  • 3 public API surface tests passed
  • scripts/build-cli.ps1 -SkipTests completed successfully, including NativeAOT publish and packaging

The unfiltered scripts/build-cli.ps1 was also run; compilation and packaging succeeded, while unrelated existing environment-dependent tests failed in live NuGet feed, crash-dump, and recording-output cases.

Retain the live UIA provider element inside the internal UiElement context so one-shot operations can act on the element they already resolved. Keep the serialized DTO fallback and stale-element behavior intact, and add deterministic resolution-count coverage across all affected operations.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings September 14, 2026 23:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Provider errors are incorrectly reported as stale, and several optimized paths lack regression assertions.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Retains live UI Automation provider elements to avoid redundant tree resolution during one-shot operations.

Changes:

  • Adds internal live-element context with serialized fallback.
  • Reuses retained elements across actions, inspection, capture, and window resolution.
  • Adds regression instrumentation and tests.
File summaries
File Description
UiAutomationService.Screenshot.cs Reuses retained elements during cropping.
UiAutomationService.cs Implements retention, fallback tracking, and reuse.
UiAutomationService.CaptureSupport.cs Reuses elements for window resolution.
UiElementContext.cs Stores the live provider element.
UiElement.cs Adds internal element context.
RealUiAutomationTests.Patterns.cs Verifies serialized fallback resolution.
RealUiAutomationTests.Actions.cs Tests retained-element actions and staleness.
Review details
  • Files reviewed: 7/7 changed files
  • Comments generated: 2
  • Review effort level: Balanced

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/winapp-CLI/WinApp.UIAutomation/Services/UiAutomationService.cs Outdated
Only translate UIA element-unavailable failures to stale errors and preserve other provider COM failures. Extend zero-resolution coverage to scoped inspection, ancestor inspection, and slug screenshot cropping.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The implementation is focused and correct, and the build, six targeted regressions, all 399 UI Automation tests, and three public API tests passed.

Review details
  • Files reviewed: 9/9 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@github-actions

github-actions Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Build in progress — metrics below are from a previous commit and will update when the current build finishes.

Build Metrics Report

Binary Sizes

Artifact Baseline Current Delta
CLI (ARM64) 46.12 MB 46.12 MB 📈 +2.0 KB (+0.00%)
CLI (x64) 46.03 MB 46.03 MB 📈 +1.5 KB (+0.00%)
MSIX (ARM64) 19.04 MB 19.04 MB 📈 +1.6 KB (+0.01%)
MSIX (x64) 20.18 MB 20.19 MB 📈 +1.4 KB (+0.01%)
NPM Package 39.61 MB 39.62 MB 📈 +0.9 KB (+0.00%)
NuGet Package 39.75 MB 39.75 MB 📈 +1.1 KB (+0.00%)

Test Results

5811 passed, 18 skipped out of 5829 tests in 892.3s (+2 tests, +48.0s vs. baseline)

Test Coverage

87.6% line coverage, 80.8% branch coverage · ✅ no change vs. baseline

CLI Startup Time

65ms median (x64, winapp --version) · ✅ no change vs. baseline

Try This Build

Installs the MSIX for your architecture, replacing any previously installed build. Needs the GitHub CLI — the command offers to install it and sign you in if it is missing.

& ([scriptblock]::Create((irm https://raw.githubusercontent.com/microsoft/winappCli/main/scripts/winapp-pr.ps1))) 841
Switching between builds often?

Put the tool on your PATH once:

& ([scriptblock]::Create((irm https://raw.githubusercontent.com/microsoft/winappCli/main/scripts/winapp-pr.ps1))) -AddToPath

Then this build is just:

winapp-pr 841

Run winapp-pr with no arguments to pick from a list of open PRs.


Updated 2026-09-15 00:33:07 UTC · commit cb997e8 · workflow run

@zateutsch
Zach Teutsch (zateutsch) merged commit a8f5027 into main Sep 16, 2026
30 checks passed
@zateutsch
Zach Teutsch (zateutsch) deleted the nmetulev-retain-resolved-ui-elements branch September 16, 2026 19:08
Nikola Metulev (nmetulev) added a commit that referenced this pull request Sep 17, 2026
## Description

Read `FontWeight`, `FontName`, `FontSize`, `ForegroundColor`,
`IsItalic`, and `StrikethroughStyle` across the element's whole
TextPattern document. Uniform values are invariant strings; UIA's mixed
and reserved-not-supported COM tokens become `Mixed` and `NotSupported`,
while elements without TextPattern return `Unavailable`. Provider
failures retain the existing error contract.

Unknown case-sensitive property names now fail with `invalid_arguments`
before querying the app. Omitting `--property` includes all six
attributes. The published `elementId` and string-valued `properties`
JSON envelope and existing geometry formats are unchanged.

## Usage Example

```powershell
winapp ui get-property Document -a myapp --property FontWeight --json
# {"elementId":"Document","properties":{"FontWeight":"700"}}
winapp ui get-property Document -a myapp --json
```

## Related Issue

Fixes #822. Independent of #841, #842, and #844. No query predicates,
explicit actions, selection/caret/range APIs, batch mode, or
persistence.

## Type of Change

- New feature
- Test update
- Documentation

## Checklist

- [x] New unit, CLI, and real-provider tests
- [x] Tested locally on Windows: 26 formatting/property library tests
and 28 CLI/property/public-API tests pass
- [x] `scripts/build-cli.ps1 -SkipTests` completes NativeAOT x64/arm64
publishing, npm/NuGet/MSIX packaging, and generated docs/schema
- [x] Canonical UI automation docs and shipped skill/reference updated

## Additional Notes

Real-app coverage reads native RichEdit uniform and mixed formatting
independently of selection, a Button without TextPattern, and an
HWND-based provider returning UIAutomationCore's actual
reserved-not-supported token through the repository COM projection.
Background fixtures assert they never activate. Unit tests cover
invariant conversion, actual COM sentinel identity, unknown names, and
provider-error propagation; CLI tests pin string serialization and
scrubbed errors.

Pre-human-review gate is pending automated review and CI; this PR is not
being merged by the implementation session.

---------

Co-authored-by: Nikola Metulev <711864+nmetulev@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Zach Teutsch <88554871+zateutsch@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Avoid resolving UI elements twice in one-shot operations

3 participants