fix(settings-ui): prevent Welcome navigation and close crashes #51437

Merged
yeelam-gordon opened 12:19pm on October 20, 2026 wanted to merge 11 Δ into microsoft/powertoys main from
fix/welcome-crash-20261020-1712

Pull Request Overview

  • Opened on October 20, 2026
  • Status Merged
  • Commit count 2 with first commit October 20, 2026

Total Delta

11 Total Diff Delta

Open Days

Open 16 weekdays

Test Delta

0 Diff Delta in Test Files
Breakdown by Phase

How long has this pull request spent in each phase of its lifecycle?

Fraction of total time Business days Phase
 
0.0 days Authoring 1 commit before pull request opened for review
 
0.0 days Awaiting first review
 
0.2 days Revising work with 1 commit in response to 3 reviews that left 1 comment
 
7.0 days Merge to deploy

Total time for pull request 7.2 business days from first commit authored to deploy

Author avatar

fix(settings-ui): prevent Welcome navigation and close crashes

Summary of the Pull Request

Fix two Welcome lifecycle failures: navigating away from the intro with animations disabled could crash Welcome, and closing Welcome could trigger an exception in the shared Settings process. Keep both corrections scoped to Welcome.

No visual appearance, layout, style, asset or string change is intended.

PR Checklist


  • [ ] Closes: N/A — reported directly; no linked issue.
    <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) -->

  • [ ] Communication: I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected

  • [ ] Tests: Added/updated and all pass — no automated lifecycle test added; candidate runtime validation and existing related tests are listed below.

  • [x] Localization: All end-user-facing strings can be localized — no strings changed.

  • [ ] Dev docs: Added/updated — N/A.

  • [ ] New binaries: Added on the required places — N/A; no binaries added.



  • [ ] Documentation updated: If checked, please file a pull request on our docs repo and link it here: N/A.

Detailed Description of the Pull Request / Additional comments



  • src/settings-ui/Settings.UI/SettingsXAML/Controls/WelcomeHero/WelcomeHero.xaml.cs: initialize reveal targets' Translation in OnLoaded, before the static/animated playback branch and asset loading. Both animation and cleanup consume that initialized state instead of enabling it themselves. The page configures all targets before Loaded; the collection contract now documents that ordering.


  • src/settings-ui/Settings.UI/SettingsXAML/OobeWindow.xaml.cs and OobeWindow.xaml: set the existing icon once during live initialization and remove the icon-only activation subscription. This avoids looking up an AppWindow from a late activation after Welcome has closed.

These are view-layer lifecycle responsibilities: composition visuals stay in the control and the native window icon stays in live window initialization. No new view-model dependency, tracking state, flags, catches, theme/navigation changes, dependencies, settings schema changes, or unrelated window fixes.

Validation Steps Performed

Windows x64 Debug candidate, built in an isolated worktree. Commands below use repository-root-relative paths rather than machine-specific paths.

Builds

tools\build\build-essentials.cmd -Platform x64 -Configuration Debug

$repo = (git rev-parse --show-toplevel)
pwsh -NoProfile -File tools\build\build.ps1 -Platform x64 -Configuration Debug -Path "$repo\src\settings-ui\Settings.UI" "/p:SolutionDir=$repo\"

Essentials build: exit 0. After the initialization-ownership follow-up, the final Settings build completed with exit 0, zero warnings/errors, in 2m18.67s, with an explicit 1800-second timeout. The runtime checks below used that rebuilt candidate.

Candidate runtime validation

Recorded candidate demo (40 seconds, reduced motion)

Real candidate at 1ce948463f7ee45f2b079a5e13f1db41bf9b5def: open Welcome, navigate to Advanced Paste, close Welcome, navigate Settings Home → General, reopen Welcome and close it again. The cropped app-only recording keeps Settings visible after both closes. It was captured with winapp ui record while native UI Automation drove the candidate; no recreated UI. Only capture borders were cropped, with no cuts or speed changes. No audio.

https://github.com/user-attachments/assets/6945a117-d917-42e7-b81c-66ece5786cde

Capture command (the HWND belongs to the candidate Settings window):

winapp ui record -w <Settings-HWND> --capture-screen --duration-sec 40 --fps 10 --max-edge 1600 --frames -o welcome-lifecycle-public.mp4

Recording and action driver: exit 0. The uploaded H.264 MP4 is 950×708 after privacy cropping. All distinct capture frames and representative frames extracted from the final video were inspected before upload. The animation preference was not changed.

From the candidate output directory, with its matching PDBs:

winapp run . --exe PowerToys.Settings.exe --debug-output --symbols --unregister-on-exit

The unpackaged output required a temporary development manifest in the build output:

winapp manifest generate . --package-name PowerToysWelcomeCrashDiag20261020 --publisher-name CN=PowerToysWelcomeCrashDiag --executable .\PowerToys.Settings.exe --description "Temporary Welcome crash diagnostics"

Check
Result

Animations disabled: navigate Welcome to Advanced Paste, then close Welcome
PASS; fresh candidate process; Settings survived

Animations disabled: independently open Welcome and close it without navigating, with Settings visible
PASS; separate fresh candidate process; Settings survived

Animations enabled: navigate Welcome to Advanced Paste, then close Welcome
PASS; fresh candidate process; Settings survived

Animations enabled: independently open Welcome and close it without navigating, with Settings visible
PASS; separate fresh candidate process; Settings survived

Reopen Welcome after closing it, then close it again
PASS in all four completed runs

Navigate Settings to General after closing Welcome; verify actual page content
PASS in all four completed runs

All four fresh candidate runs used both requested debugger flags and matching PDBs; each UI driver exited 0. Complete captured debugger logs contained no new matching Translation/icon, unhandled-exception or crash signatures. This is not a claim of zero generic first-chance CLR events. The animation preference and candidate-written shared version metadata were restored afterward.

After assertions, owned candidate processes were deliberately terminated for bounded cleanup. Their debugger exit -1 reflects that cleanup, not a crash. The temporary development package was explicitly unregistered (exit 0).

Existing related tests

The Settings unit-test project was built successfully, then:

& 'C:\Program Files\Microsoft Visual Studio\18\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe' `

'.\Debug\x64\tests\SettingsTests\net10.0-windows10.0.26100.0\Settings.UI.UnitTests.dll' `
/Platform:x64 `
'/TestCaseFilter:FullyQualifiedName~WelcomeHeroLayoutTests|FullyQualifiedName~WelcomeHeroWarpTests' `
'/Logger:trx;LogFileName=welcome-hero-focused.trx'

28/28 passed, exit 0. These cover related layout/warp behavior and were run during the Translation-fix stage; they are not lifecycle regression tests. The focused lifecycle proof is the actual final-candidate UI flow above. No source-text assertion test was retained, and no new runtime-test infrastructure was introduced for this small fix.

git diff --check also passed. Remote CI and maintainer review are separate from this local validation; no CI-completion claim is made. Only the newly captured sanitized demo is uploaded; private diagnostic logs, dumps and earlier screenshots remain local.

Comments Threads Pending Resolution

ljharb reviewed on October 20, 2026
ljharb left a comment

### 🟢 Approval recommended

No blocking issues remain in these narrowly scoped lifecycle fixes, supported by the reported candidate runtime validation.

**No open issues** 🎉

Review effort: Balanced

ljharb reviewed on October 20, 2026
ljharb left a comment

### 🟢 Approval recommended

The fixes are narrowly scoped, no blocking issues remain, and reported final-candidate validation covers both lifecycle failures.

**No open issues** 🎉

What changed in this PR

Fixes two Welcome lifecycle crashes while keeping changes scoped to Welcome.

**Changes:**
- Enable Translation before resetting reveal animations, including when animations are disabled.
- Set the window icon during initialization instead of activation, avoiding access after close.

| File | Description |
| ---- | ----------- |
| src/​settings-ui/​Settings.UI/​SettingsXAML/​OobeWindow.xaml.cs | Moves icon setup into the constructor. |
| src/​settings-ui/​Settings.UI/​SettingsXAML/​OobeWindow.xaml | Removes the icon-only activation subscription. |
| src/​settings-ui/​Settings.UI/​SettingsXAML/​Controls/​WelcomeHero/​WelcomeHero.xaml.cs | Initializes Translation before animation cleanup. |

Review effort: Balanced

Resolved Comment Threads

No resolved comments have been left on this PR.