Files
Genarrative/apps/ai-game-creator-shell/src-tauri/windows/installer-hooks.nsh
T
kdletters 13a15fed5c
Project CI / AI game creator shell Rust crates (push) Successful in 3m5s
Project CI / AI game creator shell Rust lane 2/2 (push) Successful in 4m24s
Project CI / AI game creator shell Rust lane 1/2 (push) Successful in 5m20s
Project CI / Backend tests (push) Successful in 6m42s
Project CI / Frontend tests (push) Successful in 3m2s
Project CI / Native shell tests (push) Successful in 7m16s
Project CI / AI game creator shell web tests (push) Successful in 3m17s
Project CI / Repository checks (push) Successful in 6m25s
修复 AGC 渠道更新互相终止与快捷方式迁移
为 release 与自定义渠道注入独立主程序名,隔离 Windows 更新进程。

新增 release 旧安装目录与快捷方式迁移钩子,保护 dev 历史目录清理。

同步渠道规范、共享决策与排障记录,补充发布脚本回归测试。
2026-10-04 11:45:20 +08:00

115 lines
6.4 KiB
NSIS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
; AGC dev 渠道安装身份改名的迁移钩子(NSIS installer hooks,随 Windows 包体编译)。
;
; 背景:dev 渠道的展示名改过两次(Genarrative AI Game Creator → 陶泥儿 → 陶泥儿开发版),
; identifier 保持不变。Tauri 的 NSIS 模板在更新模式(/UPDATE)与 /NS 下**不创建快捷方式**,
; 只会把「同名」快捷方式的目标改写回主程序名(见 installer.nsi 的 CreateOrUpdate*Shortcut)。
; 展示名一改,旧快捷方式既不会被改写、也不会被新建,于是升级后:
; - 旧安装目录与旧快捷方式留在原地,桌面快捷方式继续拉起旧 exe;
; - 旧 exe 的更新器仍然指向同一份 latest.json,又一次把新版本装进新目录并自动启动。
; 用户看到的就是「更新后自动启动的是新版,但桌面快捷方式打开的还是旧的」这个循环。
;
; 因此安装结束时做两件事:
; 1. 旧身份(改名前的展示名)的快捷方式、安装目录与卸载项整体清理,旧 exe 不再能被拉起;
; 2. 被迁移过的机器按当前身份补建快捷方式:桌面图标只在用户原本就有旧图标时迁移,
; 不替用户新增;开始菜单图标始终补建,避免自更新后应用失去入口。
;
; 该文件只注入 dev 渠道(改名发生在 dev 渠道)的 Windows 包;其它渠道的展示名从未变过,
; 不能拿这份旧身份表去删它们的安装。
;
; ⚠️ 编译期位置(改本文件前必读):Tauri 2.11 的 NSIS 模板在 installer.nsi 第 28 行
; `!include` 本文件,位置早于 `!define INSTALLMODE` / `!define MAINBINARYNAME` 等模板常量,
; 也早于 `!addplugindir "${ADDITIONALPLUGINSPATH}"`(nsis_tauri_utils 插件目录)。所以顶层只能放
; !define / Var / !macro 这类声明:
; - 顶层引用 `${MAINBINARYNAME}`、`${PRODUCTNAME}` 会命中未定义常量(makensis warning 6000),
; 字符串被静默替换成空文本;
; - 顶层写 `!if "${INSTALLMODE}" == "currentUser"` 会走错分支(此时 INSTALLMODE 还是空值);
; - 顶层调用 nsis_tauri_utils::* 会直接 `Plugin not found`,打包在 makensis 这一步整条中断。
; 可执行逻辑一律写进 !macro:宏体在模板的 `!insertmacro NSIS_HOOK_*` 处展开(Section Install,
; 位于 addplugindir 之后),那时模板常量与插件都已就绪。
; 旧展示名表:以后再改展示名,必须在这里追加旧名,否则升级后旧快捷方式会继续指向旧安装。
!define AGC_LEGACY_IDENTITY_1 "陶泥儿"
!define AGC_LEGACY_IDENTITY_2 "Genarrative AI Game Creator"
!define AGC_RELEASE_MAIN_BINARY "genarrative-ai-game-creator-shell-release"
Var AgcLegacyIdentity
Var AgcLegacyInstallDir
Var AgcMigratedLegacyDesktopShortcut
Var AgcLegacyOwnedByRelease
; 清理一个旧身份。调用方先把旧展示名写进 $AgcLegacyIdentity,再 !insertmacro 本宏;宏不返回错误。
; 只在「旧展示名目录下确实存在我们的主程序」时才动手,避免误删同名目录;
; 当前安装目录 $INSTDIR 永不进入删除路径。
!macro AgcMigrateLegacyIdentity
StrCpy $AgcLegacyInstallDir ""
StrCpy $AgcLegacyOwnedByRelease 0
${If} ${FileExists} "$LOCALAPPDATA\$AgcLegacyIdentity\${MAINBINARYNAME}.exe"
StrCpy $AgcLegacyInstallDir "$LOCALAPPDATA\$AgcLegacyIdentity"
${ElseIf} ${FileExists} "$PROGRAMFILES64\$AgcLegacyIdentity\${MAINBINARYNAME}.exe"
StrCpy $AgcLegacyInstallDir "$PROGRAMFILES64\$AgcLegacyIdentity"
${EndIf}
${If} $AgcLegacyInstallDir != ""
${AndIf} $AgcLegacyInstallDir != $INSTDIR
; release 新包使用独立主程序名;同一旧展示名目录若已有该文件,不能当作旧 dev 清理。
${If} ${FileExists} "$AgcLegacyInstallDir\${AGC_RELEASE_MAIN_BINARY}.exe"
StrCpy $AgcLegacyOwnedByRelease 1
${EndIf}
${EndIf}
${If} $AgcLegacyInstallDir != ""
${AndIf} $AgcLegacyInstallDir != $INSTDIR
${AndIf} $AgcLegacyOwnedByRelease = 0
; 桌面图标:只有目标正好指向旧目录的主程序时才删,避免误删同名的用户快捷方式。
!insertmacro IsShortcutTarget "$DESKTOP\$AgcLegacyIdentity.lnk" "$AgcLegacyInstallDir\${MAINBINARYNAME}.exe"
Pop $0
${If} $0 = 1
StrCpy $AgcMigratedLegacyDesktopShortcut 1
!insertmacro UnpinShortcut "$DESKTOP\$AgcLegacyIdentity.lnk"
Delete "$DESKTOP\$AgcLegacyIdentity.lnk"
${EndIf}
; 开始菜单图标:必须先删掉,否则它会在当前身份图标补建后继续指向旧 exe。
!insertmacro IsShortcutTarget "$SMPROGRAMS\$AgcLegacyIdentity.lnk" "$AgcLegacyInstallDir\${MAINBINARYNAME}.exe"
Pop $0
${If} $0 = 1
!insertmacro UnpinShortcut "$SMPROGRAMS\$AgcLegacyIdentity.lnk"
Delete "$SMPROGRAMS\$AgcLegacyIdentity.lnk"
${EndIf}
; 旧安装目录与卸载项整体清理:旧 exe 留着就会继续把新版本装进新目录。
; 先结束残留的旧实例(同名主程序):更新路径下调用方通常已退出,这里兜住手动启动的情况。
!if "${INSTALLMODE}" == "currentUser"
nsis_tauri_utils::KillProcessCurrentUser "${MAINBINARYNAME}.exe"
Pop $0
!else
nsis_tauri_utils::KillProcess "${MAINBINARYNAME}.exe"
Pop $0
!endif
RMDir /r "$AgcLegacyInstallDir"
; 卸载项按展示名登记,旧名与当前名不同,必须按旧名清掉,否则「应用和功能」里会留下孤儿条目。
DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\$AgcLegacyIdentity"
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\$AgcLegacyIdentity"
DeleteRegKey HKCU "Software\${MANUFACTURER}\$AgcLegacyIdentity"
${EndIf}
!macroend
!macro NSIS_HOOK_POSTINSTALL
StrCpy $AgcLegacyIdentity "${AGC_LEGACY_IDENTITY_1}"
!insertmacro AgcMigrateLegacyIdentity
StrCpy $AgcLegacyIdentity "${AGC_LEGACY_IDENTITY_2}"
!insertmacro AgcMigrateLegacyIdentity
; 迁移过的机器补建当前身份的快捷方式(更新模式下模板不会创建)。
StrCpy $R0 "$INSTDIR\${MAINBINARYNAME}.exe"
${IfNot} ${FileExists} "$SMPROGRAMS\${PRODUCTNAME}.lnk"
CreateShortCut "$SMPROGRAMS\${PRODUCTNAME}.lnk" "$R0"
!insertmacro SetLnkAppUserModelId "$SMPROGRAMS\${PRODUCTNAME}.lnk"
${EndIf}
${If} $AgcMigratedLegacyDesktopShortcut = 1
CreateShortCut "$DESKTOP\${PRODUCTNAME}.lnk" "$R0"
!insertmacro SetLnkAppUserModelId "$DESKTOP\${PRODUCTNAME}.lnk"
${EndIf}
!macroend