From 230b6485d91a8fc5e171082ed4dd9e7d8ea39ac1 Mon Sep 17 00:00:00 2001 From: Sofia Alves Figueredo Date: Sun, 25 Oct 2026 21:23:43 -0300 Subject: [PATCH] fix(windows): keep the shortcut icon after an update (#1114) (#1391) * fix(windows): keep the shortcut icon after an update (#1114) The MSI's Start menu shortcut took its icon from the WiX , which Windows Installer caches under %APPDATA%\Microsoft\Installer\{ProductCode}\. Every update is a major upgrade with a new ProductCode, so the old folder is deleted. A taskbar pin is a copy of the shortcut that the update never touches, so it kept pointing at the deleted file and lost its icon. Drop the Icon from the shortcut so it shows the icon embedded in deckcraft.exe, whose path survives updates. The stays for ARPPRODUCTICON. A test keeps shortcuts from naming an MSI icon again. Co-Authored-By: Claude Sonnet 5.5 * contributors: credit Sofia Alves Figueredo by real name Co-Authored-By: Claude Sonnet 5.5 * fix(windows): make the Start menu shortcut non-advertised (#1114) Addresses the review comment: without an MSI Icon, a non-advertised shortcut targets the installed exe directly and takes its embedded icon. Co-Authored-By: Claude Sonnet 5.5 * fix(windows): package.ps1 rejects a deckcraft.exe with no embedded icon (#1114) The shortcuts now take the exe's own icon, and -SkipBuild packages an existing exe that may come from a build without DECKCRAFT_REQUIRE_WINRES=1. Count its icons with ExtractIconEx and stop before WiX when there are none. Co-Authored-By: Claude Sonnet 5.5 --------- Co-authored-by: Claude Sonnet 5.5 --- ROADMAP.md | 2 ++ apps/deckcraft/src/main.rs | 23 +++++++++++++++++++++++ contributors/people.toml | 3 +++ packaging/windows/deckcraft.wxs | 10 ++++++++-- packaging/windows/package.ps1 | 9 +++++++++ 5 files changed, 45 insertions(+), 2 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index b52abe28..b04c4b69 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -137,6 +137,7 @@ app's JSON control channel (`deckcraft --control PORT`). | Date | What landed | |---|---| +| 2026-10-25 | Windows installer: the Start menu shortcut takes the icon embedded in `deckcraft.exe` instead of an MSI ``, so a taskbar pin keeps its icon after an update (#1114); a pin that already lost it has to be unpinned and pinned again once | | 2026-10-24 | AutoFormat as you type: a paragraph that starts with `*`, `-`, `--`, `>`, `<>`, `1.`, `1)`, `I.`, `i.`, `A.`, `a.` or `a)` and a space or tab becomes a bulleted or numbered list in that style; Backspace right after puts the typed text back, and Tools ▸ AutoCorrect and `text.autocorrect {lists}` turn it off | | 2026-10-24 | Tables: while the caret is in a cell, dragging into another cell selects that range of cells (shaded, merged cells taken in whole), and Shift+arrow grows or shrinks it; formatting applies to the selected cells only, and Delete clears their text and keeps the table | | 2026-10-24 | Preferences ▸ Measurement units: inches or centimetres. The Format pane's Size and Position fields, Shape Format ▸ Size on the ribbon, the Slide Size dialog and the ruler show and take the chosen unit; the deck still stores points (#1326) | @@ -293,6 +294,7 @@ app's JSON control channel (`deckcraft --control PORT`). | Date | Change | Summary | |---|---|---| +| 2026-10-25 | trivial | Progress log: Windows shortcut icon survives updates (#1114). Scores and milestone names unchanged | | 2026-10-24 | trivial | Progress log: selecting a range of table cells by dragging. Scores and milestone names unchanged | | 2026-10-24 | trivial | Progress log: measurement units in centimetres (#1326). Scores unchanged | | 2026-10-22 | trivial | Progress log: Animation Pane ▸ Play From. Scores unchanged | diff --git a/apps/deckcraft/src/main.rs b/apps/deckcraft/src/main.rs index aa7e2611..605dc84a 100644 --- a/apps/deckcraft/src/main.rs +++ b/apps/deckcraft/src/main.rs @@ -430,4 +430,27 @@ mod tests { assert_eq!(mac, win, "macOS and Windows offer different file types"); assert_eq!(mac, linux, "macOS and Linux offer different file types"); } + + /// #1114: a shortcut that names an MSI `` shows a blank icon once an update deletes the + /// cached copy of it, and a taskbar pin (a copy of the shortcut) is never repaired. Shortcuts + /// take the icon embedded in `deckcraft.exe`; only `ARPPRODUCTICON` uses the MSI ``. + #[test] + fn windows_shortcuts_use_the_icon_embedded_in_the_exe() { + let wxs = include_str!("../../../packaging/windows/deckcraft.wxs"); + let shortcuts: Vec<&str> = wxs.split("").next()).collect(); + assert!(!shortcuts.is_empty(), "deckcraft.wxs has no shortcut"); + for shortcut in shortcuts { + assert!(!shortcut.contains("Icon="), "a shortcut names an MSI :{shortcut}"); + } + assert!(wxs.contains(" + + Description="DeckCraft presentations and slide shows" WorkingDirectory="INSTALLFOLDER" Advertise="no" /> diff --git a/packaging/windows/package.ps1 b/packaging/windows/package.ps1 index 7ebbcbbe..6023a722 100644 --- a/packaging/windows/package.ps1 +++ b/packaging/windows/package.ps1 @@ -83,6 +83,15 @@ foreach ($check in @(@('deckcraft.exe', 2), @('deckcraft-cli.exe', 3))) { if ($h.Subsystem -ne $check[1]) { throw "$($check[0]) has PE subsystem $($h.Subsystem), expected $($check[1])" } Write-Output "ok $($check[0]): $Arch, PE subsystem $($h.Subsystem)" } + +# The Start menu shortcut is not advertised and names no MSI icon, so it shows the icon embedded in +# deckcraft.exe (#1114). -SkipBuild takes whatever binary is already there, which may come from a +# build without DECKCRAFT_REQUIRE_WINRES=1 whose resource compilation failed: refuse an exe with no +# icon instead of shipping shortcuts with a generic one. ExtractIconEx with index -1 counts them. +Add-Type -Namespace DeckCraft -Name Shell -MemberDefinition '[DllImport("shell32.dll", CharSet = CharSet.Unicode)] public static extern uint ExtractIconEx(string file, int index, IntPtr[] large, IntPtr[] small, uint icons);' +$Icons = [DeckCraft.Shell]::ExtractIconEx((Join-Path $Bin 'deckcraft.exe'), -1, $null, $null, 0) +if ($Icons -eq 0) { throw 'deckcraft.exe has no embedded icon: rebuild it with DECKCRAFT_REQUIRE_WINRES=1 (omit -SkipBuild)' } +Write-Output "ok deckcraft.exe: $Icons embedded icon group(s)" $Stage = Join-Path $TargetDir "windows-package\$Arch" Remove-Item -Recurse -Force $Stage -ErrorAction SilentlyContinue New-Item -ItemType Directory -Force -Path $Stage | Out-Null