Skip to content

Commit 640ce71

Browse files
committed
Add Windows Installer diagnostics
1 parent e3bbbef commit 640ce71

4 files changed

Lines changed: 92 additions & 0 deletions

File tree

data/error-recipes.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,30 @@
284284
"不要把安装器残留目录当成最终游戏目录"
285285
]
286286
},
287+
{
288+
"id": "windows-installer-msi",
289+
"title": "Windows Installer/MSI 安装器",
290+
"category": "package",
291+
"level": "warning",
292+
"patterns": [
293+
"\\bmsiexec(\\.exe)?\\b",
294+
"\\bmsi\\.dll\\b",
295+
"windows installer package",
296+
"this installation package could not be opened",
297+
"there is a problem with this windows installer package",
298+
"another installation is already in progress",
299+
"\\berror (1603|1618|1619|1620|1639)\\b.*\\b(msi|installer|installation)\\b",
300+
"\\b(msi|installer|installation)\\b.*\\berror (1603|1618|1619|1620|1639)\\b"
301+
],
302+
"cause": ".msi 是 Windows Installer 安装包,不是普通游戏 exe。旧游戏安装盘常把 MSI 与 CAB、MST、setup.ini 或语言资源分开放置;路径、权限、缺少相邻文件或已有安装进程都可能导致 1603/1618/1619/1620 等错误。",
303+
"action": "优先使用 GalAid 的安装介质入口打开 MSI,让系统通过 msiexec 安装;保持 MSI 与同目录 CAB/MST/安装资源在原相对位置,必要时移动到本地英文短路径,安装完成后重扫安装后的游戏目录。",
304+
"checklist": [
305+
"确认报错来自 .msi 或 msiexec,而不是游戏主程序",
306+
"保持 MSI 与 CAB/MST/setup.ini 等相邻文件在同一套目录",
307+
"避开网络盘、压缩包预览窗口和过深/乱码路径",
308+
"等待其他安装进程结束后再从 GalAid 安装介质入口重试"
309+
]
310+
},
287311
{
288312
"id": "dotnet-runtime",
289313
"title": ".NET 运行环境",

docs/ERROR_RECIPES.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,21 @@ Good InstallShield clues:
142142
- `data1.cab is missing`
143143
- `isdata.hdr could not be opened`
144144

145+
## Windows Installer/MSI Evidence
146+
147+
Keep MSI guidance separate from generic installer wording. The rule should only fire when the error clearly points to Windows Installer, `msiexec`, or MSI-specific error codes with installer context.
148+
149+
Good Windows Installer clues:
150+
151+
- `msiexec.exe`
152+
- `msi.dll`
153+
- `This installation package could not be opened`
154+
- `There is a problem with this Windows Installer package`
155+
- `Another installation is already in progress`
156+
- `Error 1603 during installation`
157+
- `MSI error 1619`
158+
- `Installer error 1620`
159+
145160
## Contribution Checklist
146161

147162
- Keep the rule narrow enough to avoid noisy matches.

src/error-recipes.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,30 @@ window.GALAID_ERROR_RECIPES = [
286286
"不要把安装器残留目录当成最终游戏目录"
287287
]
288288
},
289+
{
290+
"id": "windows-installer-msi",
291+
"title": "Windows Installer/MSI 安装器",
292+
"category": "package",
293+
"level": "warning",
294+
"patterns": [
295+
"\\bmsiexec(\\.exe)?\\b",
296+
"\\bmsi\\.dll\\b",
297+
"windows installer package",
298+
"this installation package could not be opened",
299+
"there is a problem with this windows installer package",
300+
"another installation is already in progress",
301+
"\\berror (1603|1618|1619|1620|1639)\\b.*\\b(msi|installer|installation)\\b",
302+
"\\b(msi|installer|installation)\\b.*\\berror (1603|1618|1619|1620|1639)\\b"
303+
],
304+
"cause": ".msi 是 Windows Installer 安装包,不是普通游戏 exe。旧游戏安装盘常把 MSI 与 CAB、MST、setup.ini 或语言资源分开放置;路径、权限、缺少相邻文件或已有安装进程都可能导致 1603/1618/1619/1620 等错误。",
305+
"action": "优先使用 GalAid 的安装介质入口打开 MSI,让系统通过 msiexec 安装;保持 MSI 与同目录 CAB/MST/安装资源在原相对位置,必要时移动到本地英文短路径,安装完成后重扫安装后的游戏目录。",
306+
"checklist": [
307+
"确认报错来自 .msi 或 msiexec,而不是游戏主程序",
308+
"保持 MSI 与 CAB/MST/setup.ini 等相邻文件在同一套目录",
309+
"避开网络盘、压缩包预览窗口和过深/乱码路径",
310+
"等待其他安装进程结束后再从 GalAid 安装介质入口重试"
311+
]
312+
},
289313
{
290314
"id": "dotnet-runtime",
291315
"title": ".NET 运行环境",

tests/galaid-smoke.spec.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,35 @@ test("InstallShield installer recipe routes old setup media failures", async ({
310310
expect(result.genericCabinet).not.toContain("installshield-runtime");
311311
});
312312

313+
test("Windows Installer MSI recipe keeps installer error codes contextual", async ({ page }) => {
314+
await page.goto("/");
315+
316+
const result = await page.evaluate(() => {
317+
const examples = [
318+
"msiexec.exe failed to open the package.",
319+
"MSI.DLL could not be loaded.",
320+
"This installation package could not be opened.",
321+
"There is a problem with this Windows Installer package.",
322+
"Another installation is already in progress.",
323+
"Error 1603 during installation.",
324+
"MSI error 1619.",
325+
"Installer error 1620.",
326+
];
327+
328+
return {
329+
positives: examples.map((text) => buildErrorDiagnostics(text).matches.map((match) => match.id)),
330+
genericErrorCode: buildErrorDiagnostics("Error 1603 appeared in the game log.").matches.map((match) => match.id),
331+
genericInstaller: buildErrorDiagnostics("The folder has an installer note in the readme.").matches.map((match) => match.id),
332+
};
333+
});
334+
335+
for (const matches of result.positives) {
336+
expect(matches).toContain("windows-installer-msi");
337+
}
338+
expect(result.genericErrorCode).not.toContain("windows-installer-msi");
339+
expect(result.genericInstaller).not.toContain("windows-installer-msi");
340+
});
341+
313342
test("package sample shows archive and image preflight without treating it as runnable", async ({ page }) => {
314343
await page.goto("/");
315344

0 commit comments

Comments
 (0)