From 4ee9aa5ab543ddb974bde6651cd9d9650ea14eac Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Thu, 4 Jun 2026 14:13:43 -0700 Subject: [PATCH] install.ps1: prime shell image list for new shortcuts (blank-icon race fix) Diagnosis this cycle: the .ico is well-formed (6 BMP frames 16-256px) and the shell resolves the logo at every size (verified via SHGetFileInfo + SHGetImageList/ImageList_GetIcon on the system image list, all sizes incl. the 256px jumbo slot the desktop draws). The residual blank is a first-paint race: Explorer lazily extracts a .lnk's icon and a miss (icon not yet flushed, cache just cleared) gets cached blank. Force the extraction at install time via SHGetFileInfo(SHGFI_SYSICONINDEX) per .lnk, populating the per-session image list both Desktop and Start Menu draw from. WoA path only, try/catch-wrapped. Co-Authored-By: Claude Opus 4.8 --- install.ps1 | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/install.ps1 b/install.ps1 index a39a68f6fa..3fec2f2242 100644 --- a/install.ps1 +++ b/install.ps1 @@ -1698,6 +1698,17 @@ shell.Run cmd, 0, False # (item args unused for this event). [UnslothShell.Notify]::SHChangeNotify(0x08000000, 0, $null, [System.IntPtr]::Zero) } catch {} + # Prime the shell system image list NOW so Desktop + Start Menu extract the real + # icon immediately. A lazy first-paint extraction that misses (icon not yet flushed, + # cache just cleared) is what gets cached as a blank; SHGFI_SYSICONINDEX forces the + # extraction here, while the .ico is known-present. (WoA path only; both views draw + # from this one per-session list.) + try { + if (-not ("UnslothShell.IconPrime" -as [type])) { + Add-Type -TypeDefinition 'using System; using System.Runtime.InteropServices; namespace UnslothShell { public class IconPrime { [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] struct FI { public IntPtr h; public int i; public uint a; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=260)] public string n; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=80)] public string t; } [DllImport("shell32.dll", CharSet=CharSet.Unicode)] static extern IntPtr SHGetFileInfo(string p, uint a, ref FI i, uint cb, uint f); public static void Prime(string path){ FI fi=new FI(); SHGetFileInfo(path,0,ref fi,(uint)Marshal.SizeOf(fi),0x4000); } } }' + } + foreach ($lnk in $lnks) { try { [UnslothShell.IconPrime]::Prime($lnk) } catch {} } + } catch {} } catch { substep "(could not create shortcuts: $($_.Exception.Message))" "Yellow" }