From dd9ba4de681ac07d0e7cd78d4549e9ab2a4261f2 Mon Sep 17 00:00:00 2001 From: Max Vilimpoc Date: Wed, 30 Sep 2026 13:43:02 +0200 Subject: [PATCH] dotfiles: register UI.Xaml 2.8 for the account before installing Terminal `winget install Microsoft.WindowsTerminal` failed on the Windows 10 box, on every run, with Installer failed with exit code: 0x80070002 : The system cannot find the file specified. and it was never Terminal that failed. Its manifest depends on the Microsoft.UI.Xaml.2.8 framework package, which winget 1.29.380 installs first, from a pinned 8.2310.30001.0 appx. A newer build, 8.2501.31001.0, was already staged on the machine but not registered for the account running the setup. Windows then stages nothing - "A higher version 8.2501.31001.0 of this package is already installed", AppXDeploymentServer event 735 - and reports the stage as a success; winget registers the 8.2310 package it believes it staged, by full name; there is no such package (0x80073CF1); and that is what comes out as "file not found". The WindowsTerminal step now registers the build that is already there first: Add-AppxPackage -RegisterByFamilyName, which takes no version and no elevation, and only when the account has none registered. winget then finds the dependency met and installs Terminal alone. With none on the machine either - the fresh box - the registration fails with that same 0x80073CF1, says nothing, and winget installs the framework as before. Any other failure is a one-line warning, and winget still gets its turn. It runs through Windows PowerShell: the Appx module does not load in PowerShell 7 here. Co-Authored-By: Claude Opus 5.5 --- README.md | 11 +++++++++++ setup-windows.bat | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/README.md b/README.md index cf8a85b..67e6a3b 100644 --- a/README.md +++ b/README.md @@ -354,6 +354,17 @@ missing or out of date. `PATH`; the step warns if it finds one (`winget uninstall Anthropic.ClaudeCode` removes it), and the architecture audit shows which `claude.exe` wins. +- **Windows Terminal gets its framework package registered first.** Terminal is + an MSIX that depends on `Microsoft.UI.Xaml.2.8`, which winget installs for it + from a pinned build (8.2310.30001.0). When a *newer* build is already on the + machine but not registered for the account running the setup, Windows + declines to stage the older one, winget then tries to register a package + that is not there, and what it prints is `Installer failed with exit code: + 0x80070002 : The system cannot find the file specified` — with Terminal + itself never attempted, on every run. So the batch file first registers the + build that is already there (`Add-AppxPackage -RegisterByFamilyName`, no + elevation needed), and winget then finds the dependency met. With none on + the machine it does nothing, and winget installs the framework as usual. - **Rust.** winget installs rustup (`Rustlang.Rustup`, per-user, under `%USERPROFILE%\.cargo` and `.rustup`). Its silent install is `rustup-init -y -q`, which already sets up a stable toolchain for whatever diff --git a/setup-windows.bat b/setup-windows.bat index a6bc8ea..d49edd4 100644 --- a/setup-windows.bat +++ b/setup-windows.bat @@ -213,7 +213,44 @@ call :winget ProcessExplorer Microsoft.Sysinternals.ProcessExplorer call :winget ProcessMonitor Microsoft.Sysinternals.ProcessMonitor call :winget SDelete Microsoft.Sysinternals.SDelete call :winget VSCode Microsoft.VisualStudioCode + +@rem --- Windows Terminal, after registering the framework package it needs --- +@rem +@rem Terminal is an MSIX, and its manifest depends on the Microsoft.UI.Xaml.2.8 +@rem framework package (>= 8.2306.22001.0), which winget installs first, from the +@rem 8.2310.30001.0 appx. That goes wrong when a NEWER build of the framework is +@rem already on the machine but not registered for this account - measured on +@rem the Windows 10 box, winget 1.29.380, with 8.2501.31001.0 staged and none +@rem registered for the account running this: +@rem - Windows stages nothing ("A higher version 8.2501.31001.0 of this package +@rem is already installed", AppXDeploymentServer event 735) and reports the +@rem stage as a success; +@rem - winget then registers the 8.2310 package it believes it staged, by full +@rem name, and there is no such package (0x80073CF1); +@rem - which it prints as +@rem Installer failed with exit code: 0x80070002 : The system cannot +@rem find the file specified. +@rem and Terminal itself is never attempted. On every run, since a failed +@rem run changes nothing. +@rem +@rem So register the build that is already there for this account first - by +@rem family name, which takes no version and no elevation. winget then finds the +@rem dependency met and installs Terminal alone. Asked only when this account +@rem has none registered, the case measured, so a re-run - Terminal and its +@rem framework both in place - changes nothing. +@rem +@rem With none on the machine either, the registration fails with that same +@rem 0x80073CF1, and that is not worth a line: it is the fresh box, where nothing +@rem is in winget's way and it installs the framework itself. Any other failure +@rem is reported, and winget still gets its turn. +@rem +@rem %PS64% because it is Windows PowerShell: the Appx module does not load in +@rem PowerShell 7 here ("Operation is not supported on this platform"). +call :want WindowsTerminal || goto :after_terminal +"%PS64%" -NoProfile -ExecutionPolicy Bypass -Command "$f = 'Microsoft.UI.Xaml.2.8'; if (-not (Get-AppxPackage $f)) { try { Add-AppxPackage -RegisterByFamilyName -MainPackage ($f + '_8wekyb3d8bbwe') -ErrorAction Stop; Write-Host ('[setup-windows] WindowsTerminal: registered ' + $f + ' ' + @(Get-AppxPackage $f)[0].Version + ', already on this machine, for this account.') } catch { if ($_.Exception.Message -notmatch '0x80073CF1') { Write-Host ('[setup-windows] WARNING: could not register ' + $f + ' for this account: ' + ($_.Exception.Message -split '\r?\n')[0]) } } }" call :winget WindowsTerminal Microsoft.WindowsTerminal +:after_terminal + call :winget Python Python.Python.3.13 @rem WinMerge is the one package here where winget's own preference order picks -- 2.56.0