Repository navigation
Handle minimized windows in winapp ui - #1054
Nikola Metulev (nmetulev) merged 6 commits into
Conversation
Packaged apps hosted in ApplicationFrameHost (Calculator) detach their content window while minimized, so -a <app> resolved to the hidden CoreWindow and every lookup missed. - Resolve a minimized frame-hosted app to its frame (matched by AUMID), in both the target resolver and list-windows. - focus restores a minimized target before finding the element; with no selector it restores and activates the window itself. A selected Window element is confirmed by foreground, fixing a false focus_not_acquired. - element_not_found (and empty search/inspect) on a minimized target says so and gives the exact 'winapp ui focus -w <hwnd>' to run. Read and mutating commands never restore or retry on their own. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ndow-handling-winapp-ui
There was a problem hiding this comment.
🟡 Changes recommended
Ambiguous minimized frames can still select the wrong target, while touch, pen, and record omit the new recovery hint.
2 open findings
What changed in this PR
Adds minimized frame-hosted app support to winapp ui, including window restoration, targeting, recovery guidance, tests, and documentation.
Changes:
- Resolves minimized packaged apps through their
ApplicationFrameHostframe. - Extends
ui focusto restore windows and allow selector-free activation. - Adds minimized-window recovery hints across UI commands.
| File | Description |
|---|---|
UiTargetResolver.cs |
Resolves detached CoreWindows to hosting frames. |
SystemUiQuery.cs |
Matches minimized frames by AppUserModelID. |
ISystemUiQuery.cs |
Documents minimized-frame lookup behavior. |
NativeMethods.txt |
Adds packaged-app identity APIs. |
UiTargetResolverTests.cs |
Tests minimized hosted-app resolution. |
UiErrors.cs |
Adds restoration recovery hints. |
UiSetValueCommand.cs |
Supplies target context to errors. |
UiSendKeysCommand.cs |
Supplies target context to errors. |
UiSearchCommand.cs |
Warns when empty results come from minimization. |
UiScrollIntoViewCommand.cs |
Supplies target context to errors. |
UiScrollCommand.cs |
Supplies target context to errors. |
UiScreenshotCommand.cs |
Supplies target context to errors. |
UiListWindowsCommand.cs |
Lists hosting frames instead of detached content. |
UiInvokeCommand.cs |
Supplies target context to errors. |
UiInspectCommand.cs |
Warns about minimized empty trees. |
UiHoverCommand.cs |
Supplies target context to errors. |
UiGetValueCommand.cs |
Supplies target context to errors. |
UiGetPropertyCommand.cs |
Supplies target context to errors. |
UiFocusCommand.cs |
Restores and focuses windows or elements. |
UiDragCommand.cs |
Supplies target context to errors. |
UiClickCommand.cs |
Supplies target context to errors. |
UiCommandTests.SimpleVerbs.cs |
Updates optional-selector validation. |
UiCommandTests.MinimizedWindow.cs |
Tests recovery hints and non-restoration. |
UiCommandTests.Focus.cs |
Tests restoration and window activation. |
FakeDesktopForegroundService.cs |
Models restored window state. |
SKILL.md |
Documents minimized-window recovery workflow. |
docs/usage.md |
Updates the focus command summary. |
docs/ui-automation.md |
Documents restoration behavior and troubleshooting. |
🧠 Review effort: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…ndow-handling-winapp-ui
Build Metrics ReportValidation passed. All required build and validation jobs succeeded. Binary Sizes
.NET Test Results (TRX reports)Other suites are reflected in the overall validation status above. ✅ 8347 passed, 37 skipped out of 8384 tests in 1311.7s (+16 tests, +139.8s vs. baseline) Test Coverage✅ 87.4% line coverage, 82.2% branch coverage · ✅ no change vs. baseline CLI Startup Time66ms median (x64, Try This BuildInstalls 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))) 1054Switching between builds often?Put the tool on your PATH once: & ([scriptblock]::Create((irm https://raw.githubusercontent.com/microsoft/winappCli/main/scripts/winapp-pr.ps1))) -AddToPathThen this build is just: winapp-pr 1054Run Updated 2026-10-12 16:46:27 UTC · commit |
…ch, pen, and record When several minimized frames match one app, report the ambiguity and ask for --window instead of guessing. Pass the target to the touch, pen, and record element-not-found errors so they include the restore hint. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5c725120-4d00-4fde-9849-078c42e66530
Zach Teutsch (zateutsch)
left a comment
There was a problem hiding this comment.
My review came up clean, approving. I resolved two copilot comments that the lifecycle skill didn't catch.
AmbiguousHostedAppFrameException is only caught inside the UIAutomation library, so it should not join the package's public API (PublicApiSurfaceTests). The public ISystemUiQuery docs name its base InvalidOperationException. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>


Description
winapp uicouldn't work with a minimized frame-hosted app (UWP/WinUI apps hosted inApplicationFrameHost, such as Calculator). While the app is minimized, its content window detaches from the frame.winapp uithen saw only an empty frame root and had no reliable way to restore the window.Repro (Calculator minimized; for each: input → actual → expected):
winapp ui search CalculatorResults -a calculatorwinapp ui inspect -a calculatorwinapp ui get-value CalculatorResults -a calculator/invoke num7Button -a calculatorwinapp ui focus CalculatorResults -a calculatorwinapp ui focus <root slug> -w <hwnd>winapp ui list-windows -a calculatorA minimized Win32 app (Notepad) keeps its full UI tree, so this only affects frame-hosted apps.
Design
-aresolves to its app frame, matched by AppUserModelID. If more than one frame matches, it doesn't guess.winapp ui focus: if the target window is minimized,focusrestores it, then looks for the element again (polling briefly while the content reattaches) and focuses it. The selector is now optional:focus -a <app>orfocus -w <hwnd>restores and activates the window itself. Focus on a window element is confirmed by checking the foreground window, which fixes the false exit 1.Run 'winapp ui focus -w <hwnd>' to restore it, then retry. In--jsonoutput this is therecoveryHintfield.searchandinspectprint the same hint as a warning when they find nothing.focusrestores a window. No other command restores or retries automatically, and mutating commands are never retried.Usage Example
Related Issue
None. Found by the agent UI benchmark in the separate
benchmarks/uiPR.Type of Change
Checklist
plugins/winapp/skills/(if CLI commands/workflows changed)Screenshots / Demo
N/A (CLI behavior; the benchmark results are below).
Additional Notes
Validation (Windows on Arm64):
.\scripts\build-cli.ps1 -SkipMsix -SkipNpm(Release, warnings-as-errors)dotnet run --project src\winapp-CLI\WinApp.Cli.Tests\WinApp.Cli.Tests.csproj -c Debug --no-build -- --filter "FullyQualifiedName~UiCommandTests"dotnet run --project src\winapp-CLI\WinApp.UIAutomation.Tests\WinApp.UIAutomation.Tests.csproj -c Debug --no-build.\scripts\validate-plugin-package.ps1The 12 full-suite failures are environmental and don't involve code changed here:
NugetServiceGetPackageDependenciesAsync_*/GetLatestVersionAsync_*). nuget.org can't be reached from a Microsoft corporate machine.AnalyzeDumpAsync_ManagedDumpWithDeepStack_DetectsStackOverflowShape. The test dump's .NET runtime doesn't match the Arm64 host.Benchmark (measured with the benchmark from the separate
benchmarks/uiPR):none)calc-minimized-scientificcalc-minimized-scientificcalc-running(regression check)Known limitations:
-ais ambiguous. Use-w <hwnd>to pick one.