From c2a8de310ff6e2e6c4ea9566b28598f984eadde9 Mon Sep 17 00:00:00 2001 From: Giuseppe Imperato Date: Tue, 5 May 2026 10:45:59 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20self-contained=20publish=20+=20Windows?= =?UTF-8?q?=20App=20Runtime=201.8.7=20=E2=80=94=20bump=20to=20v1.0.12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three compounding issues prevented PassKey from launching on installed systems: 1. STATUS_INVALID_IMAGE_HASH (v1.0.9/v1.0.10): Windows App Runtime 1.8.260101001 has a compatibility bug with Windows 11 25H2 (Build 26200+). Fixed by upgrading to Windows App Runtime 1.8.260416003 (released 2026-04-21). 2. ".NET must be installed" (v1.0.10/v1.0.11): The bundled dotnet-runtime installer was failing silently on machines with an existing .NET 8/9 installation (the DotNet10Installed check returned a false positive, skipping the installer). Fixed by switching PassKey.Desktop back to self-contained publishing — the .NET runtime is now bundled in the application folder, no external installer needed. 3. Microsoft.UI.Xaml.dll is NOT bundled (WindowsAppSDKSelfContained is not set), so HVCI/Code Integrity never rejects it. Bootstrap.Initialize() loads it from the system-installed Windows App Runtime at runtime. Verified working on: Windows 11 25H2 (Build 26200) — both bare metal and VirtualBox. Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 46 +++++++++++++++++++++- Installer/Download-Runtime.ps1 | 33 ++++++++++------ Installer/PassKey.iss | 34 +++++++--------- README.md | 4 +- publish.ps1 | 7 +++- src/PassKey.Desktop/PassKey.Desktop.csproj | 8 ++-- 6 files changed, 92 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 476c3ee..4083d68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,47 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.0.12] - 2026-05-05 + +### Fixed +- **".NET must be installed" startup failure**: PassKey v1.0.11 showed "You must install + or update .NET to run this application" because the bundled `.NET 10.0.7` installer + was failing silently during setup (likely due to a pre-existing .NET 8/9 installation + triggering an incorrect skip condition). The fix switches `PassKey.Desktop` back to + **self-contained** publishing: the .NET runtime is now bundled directly in the + application folder, so no separate .NET installer is required. The `.NET 10.0.7` + redistributable has been removed from the installer entirely. + Windows App Runtime 1.8.260416003 (introduced in v1.0.11) is still bundled and + continues to address the Windows 11 25H2 STATUS_INVALID_IMAGE_HASH crash. + +## [1.0.11] - 2026-05-04 + +### Fixed +- **Windows 11 25H2 crash (STATUS_INVALID_IMAGE_HASH — Windows App Runtime 1.8.260101001)**: + PassKey v1.0.10 crashed on Windows 11 25H2 (Build 26200+) with exception code `0xc000027b` + in `Microsoft.UI.Xaml.dll` even with the system-installed Windows App Runtime 1.8. + The root cause is a compatibility bug in Windows App Runtime **1.8.260101001** with + Windows 11 25H2. The fix upgrades the bundled Windows App Runtime installer and the NuGet SDK + from `1.8.260101001` to **1.8.260416003** (released 21 April 2026). + +## [1.0.10] - 2026-05-04 + +### Fixed +- **Windows 11 25H2 crash (STATUS_INVALID_IMAGE_HASH — self-contained .NET)**: PassKey v1.0.9 + crashed on Windows 11 25H2 (Build 26200+) because the self-contained .NET 10 apphost + triggers a WinRT activation incompatibility with the Windows App Runtime framework package: + `Microsoft.UI.Xaml.dll` throws `STATUS_INVALID_IMAGE_HASH` internally. The same crash + was reproducible on clean VirtualBox VMs with no third-party security software, confirming + the root cause is a Windows 11 25H2-specific behaviour. + + The fix switches `PassKey.Desktop` to **framework-dependent** publishing + (`--self-contained false`). The installer now bundles and silently installs the + **.NET 10.0.7 Runtime** (29 MB, from `builds.dotnet.microsoft.com`) before launching + PassKey, so end users still do not need to install .NET manually. + + The `BrowserHost` component remains self-contained (single-file executable, unaffected + by the WinRT issue). + ## [1.0.9] - 2026-05-04 ### Fixed @@ -148,7 +189,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Giuseppe Imperato** — concept, design, product decisions - **[Claude](https://www.anthropic.com/claude) by Anthropic** — architecture, implementation, documentation -[Unreleased]: https://github.com/pexatar/PassKey/compare/v1.0.9...HEAD +[Unreleased]: https://github.com/pexatar/PassKey/compare/v1.0.12...HEAD +[1.0.12]: https://github.com/pexatar/PassKey/compare/v1.0.11...v1.0.12 +[1.0.11]: https://github.com/pexatar/PassKey/compare/v1.0.10...v1.0.11 +[1.0.10]: https://github.com/pexatar/PassKey/compare/v1.0.9...v1.0.10 [1.0.9]: https://github.com/pexatar/PassKey/compare/v1.0.8...v1.0.9 [1.0.8]: https://github.com/pexatar/PassKey/compare/v1.0.7...v1.0.8 [1.0.7]: https://github.com/pexatar/PassKey/compare/v1.0.6...v1.0.7 diff --git a/Installer/Download-Runtime.ps1 b/Installer/Download-Runtime.ps1 index 1c229b2..88c821b 100644 --- a/Installer/Download-Runtime.ps1 +++ b/Installer/Download-Runtime.ps1 @@ -1,19 +1,28 @@ # Download-Runtime.ps1 -# Downloads the Windows App Runtime 1.8.260101001 redistributable required to -# build the PassKey installer. The file is excluded from git (> 100 MB limit). +# Downloads the redistributables required to build the PassKey installer. +# Both files are excluded from git (> 100 MB for WindowsAppRuntime, consistency for .NET). # # Usage: .\Installer\Download-Runtime.ps1 # Run once before building the installer with Inno Setup. -$url = "https://aka.ms/windowsappsdk/1.8/1.8.260101001/windowsappruntimeinstall-x64.exe" -$output = Join-Path $PSScriptRoot "WindowsAppRuntimeInstall-x64.exe" +$files = @( + @{ + Url = "https://aka.ms/windowsappsdk/1.8/1.8.260416003/windowsappruntimeinstall-x64.exe" + Output = Join-Path $PSScriptRoot "WindowsAppRuntimeInstall-x64.exe" + Label = "Windows App Runtime 1.8.7 (1.8.260416003)" + } + # Note: .NET runtime is no longer needed here. + # PassKey.Desktop is published self-contained — the .NET runtime is bundled + # in the application folder, so end users do not need .NET installed. +) -if (Test-Path $output) { - Write-Host "Already present: $output" -ForegroundColor Green - exit 0 +foreach ($f in $files) { + if (Test-Path $f.Output) { + Write-Host "Already present: $($f.Label)" -ForegroundColor Green + continue + } + Write-Host "Downloading $($f.Label)..." -ForegroundColor Cyan + Invoke-WebRequest -Uri $f.Url -OutFile $f.Output -UseBasicParsing + $sizeMB = [math]::Round((Get-Item $f.Output).Length / 1MB, 1) + Write-Host "Done — $sizeMB MB saved to: $($f.Output)" -ForegroundColor Green } - -Write-Host "Downloading Windows App Runtime 1.8.260101001..." -ForegroundColor Cyan -Invoke-WebRequest -Uri $url -OutFile $output -UseBasicParsing -$sizeMB = [math]::Round((Get-Item $output).Length / 1MB, 1) -Write-Host "Done — $sizeMB MB saved to: $output" -ForegroundColor Green diff --git a/Installer/PassKey.iss b/Installer/PassKey.iss index 7f83cbb..c5be3af 100644 --- a/Installer/PassKey.iss +++ b/Installer/PassKey.iss @@ -4,8 +4,8 @@ [Setup] AppId={{A7F3C2D1-8E4B-4F9A-B6D5-3C1E7A2F0D84} AppName=PassKey -AppVersion=1.0.9 -AppVerName=PassKey 1.0.9 +AppVersion=1.0.12 +AppVerName=PassKey 1.0.12 AppPublisher=Giuseppe Imperato AppPublisherURL=https://github.com/pexatar/PassKey AppSupportURL=https://github.com/pexatar/PassKey/issues @@ -21,10 +21,10 @@ SolidCompression=yes ArchitecturesAllowed=x64compatible ArchitecturesInstallIn64BitMode=x64os MinVersion=10.0.17763 -PrivilegesRequired=lowest -PrivilegesRequiredOverridesAllowed=dialog +PrivilegesRequired=admin UninstallDisplayIcon={app}\PassKey.Desktop.exe WizardStyle=modern +SetupLogging=yes [Languages] Name: "english"; MessagesFile: "compiler:Default.isl" @@ -39,9 +39,9 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; Flags: unchecked [Files] ; Windows App Runtime 1.8 redistributable — installed silently before the app launches. -; HVCI (Hypervisor-Protected Code Integrity) rejects DLLs that are not in the Windows -; Code Integrity system catalog. The official runtime installer registers trusted, cataloged -; DLLs; the NuGet-bundled copies (WindowsAppSDKSelfContained) do not. +; PassKey.Desktop is published self-contained (.NET bundled), so no separate .NET +; installer is needed. The App Runtime provides Microsoft.UI.Xaml.dll and WinRT +; support; it is loaded at runtime via Bootstrap.Initialize(). Source: "WindowsAppRuntimeInstall-x64.exe"; DestDir: "{tmp}"; Flags: ignoreversion deleteafterinstall ; Published self-contained output (Desktop + BrowserHost) @@ -52,21 +52,15 @@ Name: "{group}\PassKey"; Filename: "{app}\PassKey.Desktop.exe" Name: "{group}\{cm:UninstallProgram,PassKey}"; Filename: "{uninstallexe}" Name: "{autodesktop}\PassKey"; Filename: "{app}\PassKey.Desktop.exe"; Tasks: desktopicon -[Registry] -; passkey:// URL scheme handler -Root: HKCU; Subkey: "SOFTWARE\Classes\passkey"; ValueType: string; ValueData: "PassKey Protocol"; Flags: uninsdeletekey -Root: HKCU; Subkey: "SOFTWARE\Classes\passkey"; ValueType: string; ValueName: "URL Protocol"; ValueData: ""; Flags: uninsdeletekey -Root: HKCU; Subkey: "SOFTWARE\Classes\passkey\shell\open\command"; ValueType: string; ValueData: """{app}\PassKey.Desktop.exe"" ""%1"""; Flags: uninsdeletekey - -; Native Messaging Host for Chrome -Root: HKCU; Subkey: "SOFTWARE\Google\Chrome\NativeMessagingHosts\com.passkey.host"; ValueType: string; ValueData: "{app}\com.passkey.host.json"; Flags: uninsdeletevalue - -; Native Messaging Host for Firefox -Root: HKCU; Subkey: "SOFTWARE\Mozilla\NativeMessagingHosts\com.passkey.host"; ValueType: string; ValueData: "{app}\com.passkey.host.json"; Flags: uninsdeletevalue +; Registry entries for passkey:// URL scheme and Native Messaging Hosts are NOT +; written here. PassKey.Desktop.exe registers them in HKCU at first launch via +; ProtocolActivationService.EnsureRegistered() — this avoids HKCU/HKLM conflicts +; when the installer runs elevated and also keeps uninstall clean (app removes them +; on uninstall). [Run] -; 1. Install Windows App Runtime 1.8 silently (waits for completion before continuing). -; The installer is idempotent: if the runtime is already present it exits immediately. +; 1. Install Windows App Runtime 1.8 silently. +; Idempotent: exits immediately if the same or newer version is already present. Filename: "{tmp}\WindowsAppRuntimeInstall-x64.exe"; Parameters: "--quiet"; \ StatusMsg: "Installing Windows App Runtime 1.8..."; \ Flags: waituntilterminated diff --git a/README.md b/README.md index e3ed0fd..bd16198 100644 --- a/README.md +++ b/README.md @@ -57,8 +57,8 @@ PassKey stores your passwords, credit cards, identities, and secure notes in a l | Version | Platform | Type | |---------|----------|------| -| [v1.0.9](https://github.com/pexatar/PassKey/releases/tag/v1.0.9) | Windows x64 | Installer EXE | -| [v1.0.9](https://github.com/pexatar/PassKey/releases/tag/v1.0.9) | Windows x64 | Portable ZIP | +| [v1.0.12](https://github.com/pexatar/PassKey/releases/tag/v1.0.12) | Windows x64 | Installer EXE | +| [v1.0.12](https://github.com/pexatar/PassKey/releases/tag/v1.0.12) | Windows x64 | Portable ZIP | > **Requirements:** Windows 10 version 1809 (build 17763) or later, x64 processor. > No .NET runtime required — PassKey is fully self-contained. diff --git a/publish.ps1 b/publish.ps1 index 272355d..541fe28 100644 --- a/publish.ps1 +++ b/publish.ps1 @@ -18,7 +18,12 @@ dotnet publish "$root\src\PassKey.BrowserHost\PassKey.BrowserHost.csproj" ` -o "$root\$OutDir" --verbosity quiet if ($LASTEXITCODE -ne 0) { throw "BrowserHost publish failed (exit $LASTEXITCODE)" } -# 2. Publish Desktop (self-contained: bundles both WindowsAppSDK and .NET runtime) +# 2. Publish Desktop (self-contained: .NET runtime is bundled in the output folder). +# WindowsAppSDKSelfContained is NOT set, so Microsoft.UI.Xaml.dll and other +# Windows App Runtime DLLs are NOT bundled — they are loaded at runtime from the +# system-installed Windows App Runtime 1.8 via Bootstrap.Initialize(). +# This avoids both the STATUS_INVALID_IMAGE_HASH (NuGet DLLs rejected by HVCI) +# and the .NET-not-found startup failure caused by a silent .NET installer failure. Write-Host "`n[2/2] Publishing Desktop..." -ForegroundColor Yellow $platformArg = if ($Arch -eq "arm64") { "ARM64" } else { "x64" } dotnet publish "$root\src\PassKey.Desktop\PassKey.Desktop.csproj" ` diff --git a/src/PassKey.Desktop/PassKey.Desktop.csproj b/src/PassKey.Desktop/PassKey.Desktop.csproj index fe907cb..b3b6821 100644 --- a/src/PassKey.Desktop/PassKey.Desktop.csproj +++ b/src/PassKey.Desktop/PassKey.Desktop.csproj @@ -14,9 +14,9 @@ None false PassKey.Desktop - 1.0.9 - 1.0.9.0 - 1.0.9.0 + 1.0.12 + 1.0.12.0 + 1.0.12.0 app.manifest Assets\PassKey.ico DISABLE_XAML_GENERATED_MAIN @@ -28,7 +28,7 @@ - +