修复 AGC 渠道更新互相终止与快捷方式迁移
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
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
为 release 与自定义渠道注入独立主程序名,隔离 Windows 更新进程。 新增 release 旧安装目录与快捷方式迁移钩子,保护 dev 历史目录清理。 同步渠道规范、共享决策与排障记录,补充发布脚本回归测试。
This commit is contained in:
@@ -18,6 +18,7 @@ import {
|
||||
import {
|
||||
AGC_DEFAULT_CHANNEL,
|
||||
resolveChannelInstallIdentity,
|
||||
resolveChannelMainBinaryName,
|
||||
resolveReleaseChannel,
|
||||
} from './channel-identity.mjs';
|
||||
import { prepareNsisToolsetForRelease } from './nsis-toolset.mjs';
|
||||
@@ -38,6 +39,9 @@ const appRoot = fileURLToPath(new URL('..', import.meta.url));
|
||||
const devChannelInstallerHooks = fileURLToPath(
|
||||
new URL('../src-tauri/windows/installer-hooks.nsh', import.meta.url),
|
||||
);
|
||||
const releaseChannelInstallerHooks = fileURLToPath(
|
||||
new URL('../src-tauri/windows/release-installer-hooks.nsh', import.meta.url),
|
||||
);
|
||||
// Git 命令用于读取 release revision,必须在仓库根执行,不能在应用目录里执行。
|
||||
const repoRoot = path.resolve(appRoot, '..', '..');
|
||||
const defaultReleaseTarget = 'x86_64-pc-windows-msvc';
|
||||
@@ -423,6 +427,7 @@ export function createChannelConfig(
|
||||
const config = {
|
||||
productName,
|
||||
identifier,
|
||||
mainBinaryName: resolveChannelMainBinaryName(channel),
|
||||
app: {
|
||||
windows: [{ ...baseClientWindow, title: productName }],
|
||||
},
|
||||
@@ -432,10 +437,20 @@ export function createChannelConfig(
|
||||
},
|
||||
},
|
||||
};
|
||||
// 只有 dev 渠道改过展示名:它的包需要自带旧身份迁移;其它渠道不能拿这份旧名表去删安装。
|
||||
if (channel === AGC_DEFAULT_CHANNEL && target.includes('windows'))
|
||||
// dev 渠道迁移改名前的旧身份;release 渠道迁移曾使用过「陶泥儿 Release」的安装与快捷方式。
|
||||
if (
|
||||
target.includes('windows') &&
|
||||
(channel === AGC_DEFAULT_CHANNEL || channel === 'release')
|
||||
)
|
||||
config.bundle = {
|
||||
windows: { nsis: { installerHooks: devChannelInstallerHooks } },
|
||||
windows: {
|
||||
nsis: {
|
||||
installerHooks:
|
||||
channel === AGC_DEFAULT_CHANNEL
|
||||
? devChannelInstallerHooks
|
||||
: releaseChannelInstallerHooks,
|
||||
},
|
||||
},
|
||||
};
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -35,8 +35,10 @@ import {
|
||||
} from './build-release.mjs';
|
||||
import {
|
||||
AGC_APP_IDENTIFIER,
|
||||
AGC_MAIN_BINARY_NAME,
|
||||
AGC_PRODUCT_NAME,
|
||||
resolveChannelInstallIdentity,
|
||||
resolveChannelMainBinaryName,
|
||||
} from './channel-identity.mjs';
|
||||
import { supportedHostTarget } from './prepare-bundled-resources.mjs';
|
||||
|
||||
@@ -188,6 +190,7 @@ test('channel manifest URL and build-time endpoint follow the channel', () => {
|
||||
assert.deepEqual(createChannelConfig('dev', 'aarch64-apple-darwin'), {
|
||||
productName: `${AGC_PRODUCT_NAME}开发版`,
|
||||
identifier: AGC_APP_IDENTIFIER,
|
||||
mainBinaryName: AGC_MAIN_BINARY_NAME,
|
||||
app: {
|
||||
windows: [
|
||||
{
|
||||
@@ -236,6 +239,15 @@ test('channel install identity isolates co-installed builds and keeps the defaul
|
||||
productName: '陶泥儿 Beta-2',
|
||||
identifier: `${AGC_APP_IDENTIFIER}.beta-2`,
|
||||
});
|
||||
assert.equal(resolveChannelMainBinaryName('dev'), AGC_MAIN_BINARY_NAME);
|
||||
assert.equal(
|
||||
resolveChannelMainBinaryName('release'),
|
||||
`${AGC_MAIN_BINARY_NAME}-release`,
|
||||
);
|
||||
assert.equal(
|
||||
resolveChannelMainBinaryName('beta-2'),
|
||||
`${AGC_MAIN_BINARY_NAME}-beta-2`,
|
||||
);
|
||||
|
||||
// release 与其它非默认渠道通过独立 identifier 隔离运行身份与数据目录;
|
||||
// 自定义渠道另外保留可区分的产品名。
|
||||
@@ -269,6 +281,7 @@ test('channel install identity is baked into the same build-time config as the e
|
||||
const config = createChannelConfig('release', windowsTarget);
|
||||
assert.equal(config.productName, AGC_PRODUCT_NAME);
|
||||
assert.equal(config.identifier, `${AGC_APP_IDENTIFIER}.release`);
|
||||
assert.equal(config.mainBinaryName, `${AGC_MAIN_BINARY_NAME}-release`);
|
||||
assert.match(
|
||||
config.plugins.updater.endpoints[0],
|
||||
/\/release-win\/latest\.json$/u,
|
||||
@@ -280,7 +293,7 @@ test('channel install identity is baked into the same build-time config as the e
|
||||
* dev 渠道展示名改过两次(Genarrative AI Game Creator → 陶泥儿 → 陶泥儿开发版),而更新路径
|
||||
* (/UPDATE)不会重建快捷方式:改名后的包必须自带旧身份迁移,否则桌面快捷方式会一直指向旧安装。
|
||||
*/
|
||||
test('dev 渠道的 Windows 包注入改名迁移钩子,其它渠道与目标不注入', () => {
|
||||
test('渠道 Windows 包注入各自迁移钩子,且主进程文件名按渠道隔离', () => {
|
||||
withEnv({ AGC_UPDATE_OSS_BASE_URL: undefined }, () => {
|
||||
const devWindows = createChannelConfig('dev', windowsTarget);
|
||||
const hooksPath = devWindows.bundle.windows.nsis.installerHooks;
|
||||
@@ -296,10 +309,27 @@ test('dev 渠道的 Windows 包注入改名迁移钩子,其它渠道与目标
|
||||
`迁移钩子缺少旧身份:${legacyIdentity}`,
|
||||
);
|
||||
}
|
||||
assert.match(
|
||||
hooksSource,
|
||||
/AGC_RELEASE_MAIN_BINARY\s+"genarrative-ai-game-creator-shell-release"/u,
|
||||
);
|
||||
|
||||
// 改名只发生在 dev:其它渠道注入会拿 dev 的旧名表去删别人的安装。
|
||||
const releaseWindows = createChannelConfig('release', windowsTarget);
|
||||
const releaseHooksPath = releaseWindows.bundle.windows.nsis.installerHooks;
|
||||
assert.ok(releaseHooksPath);
|
||||
assert.equal(existsSync(releaseHooksPath), true);
|
||||
assert.match(readFileSync(releaseHooksPath, 'utf8'), /陶泥儿 Release/u);
|
||||
assert.equal(
|
||||
createChannelConfig('release', windowsTarget).bundle,
|
||||
releaseWindows.mainBinaryName,
|
||||
`${AGC_MAIN_BINARY_NAME}-release`,
|
||||
);
|
||||
assert.notEqual(
|
||||
devWindows.mainBinaryName,
|
||||
releaseWindows.mainBinaryName,
|
||||
'dev 与 release 的 NSIS 进程匹配名必须不同',
|
||||
);
|
||||
assert.equal(
|
||||
createChannelConfig('beta-2', windowsTarget).bundle,
|
||||
undefined,
|
||||
);
|
||||
// macOS 包没有 NSIS 安装器,不能带上 Windows 钩子。
|
||||
@@ -395,6 +425,44 @@ test('安装钩子的可执行逻辑必须全在 !macro 内,顶层不得引用
|
||||
);
|
||||
});
|
||||
|
||||
test('release 安装钩子迁移旧 Release 身份且保持编译期位置纪律', () => {
|
||||
const hooksPath = createChannelConfig('release', windowsTarget).bundle.windows
|
||||
.nsis.installerHooks;
|
||||
const hooksSource = readFileSync(hooksPath, 'utf8');
|
||||
assert.deepEqual(
|
||||
readFileSync(hooksPath).subarray(0, 3),
|
||||
Buffer.from([0xef, 0xbb, 0xbf]),
|
||||
'NSIS 中文钩子必须保留 UTF-8 BOM',
|
||||
);
|
||||
assert.match(hooksSource, /陶泥儿 Release/u);
|
||||
assert.match(hooksSource, /AGC_RELEASE_LEGACY_BINARY/u);
|
||||
assert.match(hooksSource, /NSIS_HOOK_PREINSTALL/u);
|
||||
assert.match(hooksSource, /NSIS_HOOK_POSTINSTALL/u);
|
||||
let macroDepth = 0;
|
||||
const offenders = [];
|
||||
for (const [index, rawLine] of hooksSource.split('\n').entries()) {
|
||||
const line = rawLine.trim();
|
||||
if (line === '' || line.startsWith(';')) continue;
|
||||
if (/^!macroend\b/u.test(line)) {
|
||||
macroDepth = Math.max(0, macroDepth - 1);
|
||||
continue;
|
||||
}
|
||||
if (/^!macro\b/u.test(line)) {
|
||||
macroDepth += 1;
|
||||
continue;
|
||||
}
|
||||
if (macroDepth > 0) continue;
|
||||
if (
|
||||
line.includes('::') ||
|
||||
/^(?:Function(?:End)?|Return|Delete|ReadRegStr|StrCpy|CreateShortCut)\b/u.test(
|
||||
line,
|
||||
)
|
||||
)
|
||||
offenders.push(`第 ${index + 1} 行出现顶层可执行语句:${line}`);
|
||||
}
|
||||
assert.deepEqual(offenders, []);
|
||||
});
|
||||
|
||||
/**
|
||||
* RFC 7386(tauri-utils 用 `json_patch::merge`)语义:对象递归合并,数组整体替换。
|
||||
* 这里按同样语义复现 Tauri CLI 的 `--config` 合并,用来守住"渠道配置不得丢窗口契约"。
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
export const AGC_DEFAULT_CHANNEL = 'dev';
|
||||
export const AGC_PRODUCT_NAME = '陶泥儿';
|
||||
export const AGC_APP_IDENTIFIER = 'world.genarrative.ai-game-creator';
|
||||
/**
|
||||
* Tauri/NSIS 默认按主可执行文件名查找并结束进程。
|
||||
* dev 保留历史文件名以维持既有更新链;其它渠道使用独立文件名,
|
||||
* 这样更新一个渠道时不会把另一个渠道的进程一起结束。
|
||||
*/
|
||||
export const AGC_MAIN_BINARY_NAME = 'genarrative-ai-game-creator-shell';
|
||||
|
||||
const reservedChannelNames = new Set([
|
||||
'win',
|
||||
@@ -75,3 +81,11 @@ export function resolveChannelInstallIdentity(channel = AGC_DEFAULT_CHANNEL) {
|
||||
: `${AGC_APP_IDENTIFIER}.${channel}`,
|
||||
});
|
||||
}
|
||||
|
||||
/** 渠道对应的主可执行文件名(不含平台扩展名)。 */
|
||||
export function resolveChannelMainBinaryName(channel = AGC_DEFAULT_CHANNEL) {
|
||||
validateReleaseChannel(channel);
|
||||
return channel === AGC_DEFAULT_CHANNEL
|
||||
? AGC_MAIN_BINARY_NAME
|
||||
: `${AGC_MAIN_BINARY_NAME}-${channel}`;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,9 @@ execFileSync(
|
||||
|
||||
import {
|
||||
AGC_APP_IDENTIFIER,
|
||||
AGC_MAIN_BINARY_NAME,
|
||||
resolveChannelInstallIdentity,
|
||||
resolveChannelMainBinaryName,
|
||||
} from './channel-identity.mjs';
|
||||
import {
|
||||
askHidden,
|
||||
@@ -1299,9 +1301,14 @@ if (tauriConfig.identifier !== AGC_APP_IDENTIFIER) {
|
||||
throw new Error('AI game creator shell identifier drifted');
|
||||
}
|
||||
|
||||
if (tauriConfig.mainBinaryName !== AGC_MAIN_BINARY_NAME) {
|
||||
throw new Error('AI game creator shell mainBinaryName drifted');
|
||||
}
|
||||
|
||||
if (
|
||||
tauriConfig.productName !== defaultChannelIdentity.productName ||
|
||||
tauriConfig.identifier !== defaultChannelIdentity.identifier
|
||||
tauriConfig.identifier !== defaultChannelIdentity.identifier ||
|
||||
tauriConfig.mainBinaryName !== resolveChannelMainBinaryName('dev')
|
||||
) {
|
||||
throw new Error(
|
||||
'AI game creator shell baseline config must match the default channel identity',
|
||||
@@ -1314,6 +1321,8 @@ for (const channel of ['release', 'beta-2']) {
|
||||
if (
|
||||
identity.productName === defaultChannelIdentity.productName ||
|
||||
identity.identifier === defaultChannelIdentity.identifier ||
|
||||
resolveChannelMainBinaryName(channel) ===
|
||||
resolveChannelMainBinaryName('dev') ||
|
||||
!identity.identifier.startsWith(`${AGC_APP_IDENTIFIER}.`)
|
||||
) {
|
||||
throw new Error(`channel install identity not isolated: ${channel}`);
|
||||
@@ -1631,13 +1640,11 @@ if (!viteConfigSource.includes('allow: [repoRoot]')) {
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!(
|
||||
tauriConfig.build?.beforeDevCommand?.includes(
|
||||
'run ai-game-creator-shell:dev-server',
|
||||
) || tauriConfig.build?.beforeDevCommand?.includes('run agc:serve')
|
||||
)
|
||||
) {
|
||||
if (!(
|
||||
tauriConfig.build?.beforeDevCommand?.includes(
|
||||
'run ai-game-creator-shell:dev-server',
|
||||
) || tauriConfig.build?.beforeDevCommand?.includes('run agc:serve')
|
||||
)) {
|
||||
throw new Error(
|
||||
'AI game creator shell beforeDevCommand must start the selected Vite dev server',
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "陶泥儿开发版",
|
||||
"mainBinaryName": "genarrative-ai-game-creator-shell",
|
||||
"version": "0.1.67",
|
||||
"identifier": "world.genarrative.ai-game-creator",
|
||||
"build": {
|
||||
|
||||
@@ -30,16 +30,19 @@
|
||||
; 旧展示名表:以后再改展示名,必须在这里追加旧名,否则升级后旧快捷方式会继续指向旧安装。
|
||||
!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"
|
||||
@@ -49,6 +52,15 @@ Var AgcMigratedLegacyDesktopShortcut
|
||||
|
||||
${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
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
; AGC release 渠道的 Windows 安装迁移钩子。
|
||||
;
|
||||
; release 曾使用「陶泥儿 Release」作为 productName,后来统一为「陶泥儿」。
|
||||
; Tauri 的 NSIS 更新模式不会为改名后的身份重建快捷方式,也不会自动读取旧身份的安装目录,
|
||||
; 所以这里把旧安装目录、旧快捷方式迁移到当前 release 身份。
|
||||
;
|
||||
; release 渠道同时使用独立的 MAINBINARYNAME(genarrative-ai-game-creator-shell-release),
|
||||
; NSIS 默认的按文件名查杀逻辑因此不会碰 dev 渠道的主进程。
|
||||
;
|
||||
!define AGC_RELEASE_LEGACY_IDENTITY "陶泥儿 Release"
|
||||
!define AGC_RELEASE_LEGACY_BINARY "genarrative-ai-game-creator-shell"
|
||||
|
||||
Var AgcReleaseLegacyInstallDir
|
||||
Var AgcReleaseMigratedDesktopShortcut
|
||||
|
||||
; Tauri 模板会在 Section Install 开头先执行 SetOutPath,再展开 PREINSTALL 宏。
|
||||
; 此处仍可在复制文件前改写 $INSTDIR,让旧 release 安装原地升级。
|
||||
!macro NSIS_HOOK_PREINSTALL
|
||||
StrCpy $AgcReleaseLegacyInstallDir ""
|
||||
ReadRegStr $R0 SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${AGC_RELEASE_LEGACY_IDENTITY}" "InstallLocation"
|
||||
; Tauri 将 InstallLocation 写成带引号的 REG_SZ;去掉包裹引号后再交给 FileExists。
|
||||
StrCpy $R1 $R0 1
|
||||
${If} $R1 == '$\"'
|
||||
StrCpy $R0 $R0 "" 1
|
||||
StrLen $R1 $R0
|
||||
IntOp $R1 $R1 - 1
|
||||
StrCpy $R0 $R0 $R1
|
||||
${EndIf}
|
||||
${If} $R0 != ""
|
||||
${AndIf} ${FileExists} "$R0\${AGC_RELEASE_LEGACY_BINARY}.exe"
|
||||
StrCpy $AgcReleaseLegacyInstallDir $R0
|
||||
StrCpy $INSTDIR $R0
|
||||
${EndIf}
|
||||
!macroend
|
||||
|
||||
!macro NSIS_HOOK_POSTINSTALL
|
||||
; 更新模式下模板不会重建快捷方式。先把旧名称和旧主程序名指向当前 release。
|
||||
!insertmacro IsShortcutTarget "$DESKTOP\${AGC_RELEASE_LEGACY_IDENTITY}.lnk" "$INSTDIR\${AGC_RELEASE_LEGACY_BINARY}.exe"
|
||||
Pop $0
|
||||
${If} $0 = 1
|
||||
StrCpy $AgcReleaseMigratedDesktopShortcut 1
|
||||
!insertmacro UnpinShortcut "$DESKTOP\${AGC_RELEASE_LEGACY_IDENTITY}.lnk"
|
||||
Delete "$DESKTOP\${AGC_RELEASE_LEGACY_IDENTITY}.lnk"
|
||||
${EndIf}
|
||||
|
||||
!insertmacro IsShortcutTarget "$SMPROGRAMS\${AGC_RELEASE_LEGACY_IDENTITY}.lnk" "$INSTDIR\${AGC_RELEASE_LEGACY_BINARY}.exe"
|
||||
Pop $0
|
||||
${If} $0 = 1
|
||||
!insertmacro UnpinShortcut "$SMPROGRAMS\${AGC_RELEASE_LEGACY_IDENTITY}.lnk"
|
||||
Delete "$SMPROGRAMS\${AGC_RELEASE_LEGACY_IDENTITY}.lnk"
|
||||
${EndIf}
|
||||
|
||||
; 用户可能早已把快捷方式改成当前名称,但仍指向旧主程序名。
|
||||
!insertmacro IsShortcutTarget "$DESKTOP\${PRODUCTNAME}.lnk" "$INSTDIR\${AGC_RELEASE_LEGACY_BINARY}.exe"
|
||||
Pop $0
|
||||
${If} $0 = 1
|
||||
!insertmacro SetShortcutTarget "$DESKTOP\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
|
||||
${EndIf}
|
||||
!insertmacro IsShortcutTarget "$SMPROGRAMS\${PRODUCTNAME}.lnk" "$INSTDIR\${AGC_RELEASE_LEGACY_BINARY}.exe"
|
||||
Pop $0
|
||||
${If} $0 = 1
|
||||
!insertmacro SetShortcutTarget "$SMPROGRAMS\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
|
||||
${EndIf}
|
||||
|
||||
; 开始菜单图标始终存在;桌面图标只在迁移前存在时补建,保持用户选择。
|
||||
StrCpy $R0 "$INSTDIR\${MAINBINARYNAME}.exe"
|
||||
${IfNot} ${FileExists} "$SMPROGRAMS\${PRODUCTNAME}.lnk"
|
||||
CreateShortCut "$SMPROGRAMS\${PRODUCTNAME}.lnk" "$R0"
|
||||
!insertmacro SetLnkAppUserModelId "$SMPROGRAMS\${PRODUCTNAME}.lnk"
|
||||
${EndIf}
|
||||
${If} $AgcReleaseMigratedDesktopShortcut = 1
|
||||
CreateShortCut "$DESKTOP\${PRODUCTNAME}.lnk" "$R0"
|
||||
!insertmacro SetLnkAppUserModelId "$DESKTOP\${PRODUCTNAME}.lnk"
|
||||
${EndIf}
|
||||
|
||||
; 新 release 已接管旧安装目录后,删除旧主程序,避免 dev 的迁移钩子把该目录误判为旧 dev。
|
||||
${If} $AgcReleaseLegacyInstallDir != ""
|
||||
Delete "$INSTDIR\${AGC_RELEASE_LEGACY_BINARY}.exe"
|
||||
DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${AGC_RELEASE_LEGACY_IDENTITY}"
|
||||
DeleteRegKey HKCU "Software\genarrative\${AGC_RELEASE_LEGACY_IDENTITY}"
|
||||
${EndIf}
|
||||
!macroend
|
||||
Reference in New Issue
Block a user