简介:Advanced Installer 15.2汉化版面向需要制作Windows安装包的开发者与系统管理员,围绕MSI打包、安装向导界面定制、自动化脚本、多语言部署以及升级修补等常见需求,提供较完整的中文化操作环境,可降低英文界面带来的理解与上手成本。压缩包为zip格式,大小约132.05MB;上游未提供文件总数及文件类型明细,故不展开统计。从内容构成看,资料涉及汉化版程序、更新日志说明以及Advanced Installer Architect 15.2 Portable便携版,便于在不同工作环境中直接使用并了解版本改进。其价值在于帮助读者完成安装包创建、界面与流程配置、组件依赖集成和后续更新维护,也可借助更新日志核对15.2版的新增功能与修复项。已有311人学习,适合需要兼顾MSI规范、品牌化安装体验与多平台组件集成的初中级至中级用户参考。
1. 装包师傅的老伙计:Advanced Installer 15.2 汉化版到底解决什么问题
客户机上双击 setup.exe,弹出一屏英文向导,旁边站着的 IT 管理员问“下一步点哪个”,这种场面比代码报错更尴尬。Advanced Installer 15.2 汉化版干的就是这件事:把这款可视化 installer 制作工具的界面和向导中文化,让不熟英文的同事也能照着页面把程序文件、注册表项、快捷方式、升级规则塞进一个 MSI 或 EXE 里。它适合三类人:给自己写的桌面工具做分发的小团队、接手遗留项目还要改安装脚本的维护者、以及被脚本式 installer 配置折磨过想换图形界面的人。15.2 这个版本功能边界清楚,汉化资源覆盖到主流程,日常交付够用。
2. 装之前先搞清楚:汉化版的组成、依赖与安装顺序
拿到一个汉化包最怕的是“装完发现界面还是半中半英”,或者装到一半被安全软件拦下来。这一章先把包的形态、环境依赖和安装顺序理清楚,后面所有操作都建立在这个基础上。
2.1 汉化资源的两种形态,决定了你的安装动作
市面上能拿到的汉化形态基本是两类。第一种是整体汉化安装包:安装程序本身就是中文向导,装完主程序直接是中文界面,省事但没法挑版本。第二种是补丁式:先装原版,再把一批语言资源文件覆盖到安装目录,好处是原版可选、可回退,坏处是多一步操作且容易覆盖错目录。
判断方法很简单,看压缩包结构。如果里面只有一个 setup.exe 加几个说明文件,那是第一种;如果里面是 Languages 目录、若干 .resources.dll 或者一堆同名资源文件,那就是第二种,别急着双击,先看清楚它对应哪个小版本。
我一般会把补丁包和安装目录做一次文件名比对,多出来的、对不上的文件先列出来,再决定要不要覆盖。版本错配是汉化失败最常见的原因,15.2 的资源扔进 15.1 的目录,界面会出现一半中文一半英文,甚至个别对话框直接空白。
2.2 环境依赖与安装顺序:别在最后一步翻车
Advanced Installer 15.x 这类工具依赖 .NET Framework 4.x 运行时,机器上如果只有 3.5,启动会直接报初始化失败。常见做法是先确认系统已装 4.6 以上版本,Windows 10/11 一般自带,Windows 7 的老机器要手动补。
安装顺序按这个走,几乎不会出问题:
- 退出所有正在运行的打包工具实例,任务管理器里确认没有残留进程。
- 把汉化包整个目录加入安全软件的白名单,补丁式汉化的资源文件被误判是常事,拦掉一个文件就变成半汉化。
- 用管理员权限运行安装程序,装到默认路径或者一个纯英文、无空格的路径下。
- 如果是补丁式,先启动一次原版确认能正常打开,再关闭,然后覆盖资源。
- 重新启动,进设置里把界面语言切到简体中文,重启一次让资源生效。
路径这件事值得单独说。装到D:\工具\打包\Advanced Installer这种带中文的路径下,部分老版本在生成临时工程文件时会出编码问题,构建阶段报“找不到文件”,实际上文件就在那儿。血泪经验是:安装路径、工程路径、输出路径,三处全用英文。
2.3 覆盖前先备份,出问题能一键回退
补丁式汉化没有后悔药,除非你自己留一份。覆盖之前把 Languages 目录整个复制走,出问题直接覆盖回来,比重新装一遍快得多。
# 覆盖汉化资源前,先把原始语言目录整份备份到非系统盘 $installDir = "C:\Program Files (x86)\Advanced Installer 15.2" $backupDir = "D:\backup\ai152-lang-orig" if (-not (Test-Path $backupDir)) { New-Item -ItemType Directory -Path $backupDir | Out-Null } Copy-Item -Path (Join-Path $installDir "Languages") -Destination $backupDir -Recurse -Force # 汉化包解压目录,按相对路径逐个覆盖回去 $patchDir = "D:\patch\ai152-zh" Get-ChildItem $patchDir -Recurse -File | ForEach-Object { $rel = $_.FullName.Substring($patchDir.Length).TrimStart('\') $dest = Join-Path $installDir $rel if (Test-Path $dest) { Copy-Item $_.FullName $dest -Force Write-Host "覆盖成功: $rel" } else { Write-Host "跳过,目标不存在: $rel" -ForegroundColor Yellow } }这段脚本的关键在Test-Path那一行判断。目标文件不存在时直接跳过而不是硬拷,能避免往安装目录里塞进原版根本没有的文件,那种情况往往导致主程序启动时报资源加载异常。$installDir换成你自己的实际路径,注意 64 位系统上默认装在Program Files (x86)下。备份目录别放 C 盘,重装系统时容易一起没。
覆盖完成后做一次哈希比对,确认文件真的替换成功,而不是被安全软件静默拦截:
# 比对汉化源文件与安装目录中同名文件的哈希,确认替换生效 $patchDir = "D:\patch\ai152-zh" $installDir = "C:\Program Files (x86)\Advanced Installer 15.2" Get-ChildItem $patchDir -Recurse -File | ForEach-Object { $dest = Join-Path $installDir $_.FullName.Substring($patchDir.Length).TrimStart('\') if (Test-Path $dest) { $h1 = (Get-FileHash $_.FullName -Algorithm MD5).Hash $h2 = (Get-FileHash $dest -Algorithm MD5).Hash [PSCustomObject]@{ 文件 = $_.Name 一致 = ($h1 -eq $h2) } } } | Where-Object { -not $_.一致 }只输出不一致的项,输出为空说明全部替换到位。如果有残留,多半是文件被占用或者权限不足,用管理员权限的 PowerShell 重跑一次即可。
2.4 首次启动的验证清单
装完之后别急着建工程,先按这四项过一遍:帮助菜单里的“关于”是否显示 15.2;主界面左侧导航的分组名是否全部中文;新建一个空白 MSI 工程能否正常打开各配置页;直接点构建能否成功产出一个空包。四项都过,说明环境和资源都没问题,可以进入正式打包。
其中第三项最容易被忽略。有些汉化包只覆盖了主程序资源,对话框模板没覆盖,建工程时弹出的向导还是英文,构建时又因为模板缺字段报错。早点发现比做到一半发现强。
3. 从空工程到能装的 MSI:文件、目录与注册表怎么摆
这一章开始动手。目标是从零建一个能装、能卸、装完桌面有图标、注册表里留痕的 MSI 包,把工程结构、目录映射和构建流程走通。走通这一遍,后面加功能就是在这个骨架上挂东西。
3.1 先选工程类型:纯 MSI 还是自带引导的 EXE
新建工程时第一个岔路口就在这里。纯 MSI 的优点是体积小、可被组策略批量分发、日志干净;缺点是目标机缺运行库时安装过程中途失败,用户只看到一个 1603 错误码。自带引导的 EXE 在外面套了一层引导程序,可以把 .NET Framework、VC 运行库这些前置条件塞进去,缺什么先装什么,用户体验好很多。
我的选择标准是看目标环境。公司内部几十台机器统一分发,用纯 MSI,配合域策略推送运行库;对外发给不确定环境的客户,用 EXE 引导包,把前置依赖和安装参数都封进去。
工程建好之后有几个字段必须当场填清楚,后面改起来代价很大:
| 字段 | 位置 | 填写要点 |
|---|---|---|
| Product Name | 产品信息页 | 安装后在控制面板显示的名字,别带版本号 |
| Product Version | 产品信息页 | 主版本.次版本.修订号,第四位是内部构建号不参与升级比较 |
| Manufacturer | 产品信息页 | 决定默认安装目录的一层,用英文 |
| Upgrade Code | 产品信息页 | 一次生成终身不变,同系列产品必须一致 |
| Product Code | 产品信息页 | 每次发布新版本重新生成 |
Manufacturer 用英文这点吃过亏。写中文的话默认安装路径会变成C:\Program Files (x86)\某公司\某产品,某些老系统上的安装脚本处理中文路径时会乱码。稳妥做法是 Manufacturer 用英文,显示名在界面上单独设置。
3.2 文件组织与目录属性:理解方括号里的那串变量
文件与文件夹页是工程的核心。左侧的“应用程序文件夹”默认映射到一个路径变量,形如[ProgramFilesFolder][Manufacturer][ProductName]。方括号里的东西是安装时才能确定的属性,ProgramFilesFolder会根据目标系统是 32 位还是 64 位自动选Program Files或Program Files (x86)。
几个高频属性值得记住:
[ProgramFilesFolder]程序主目录,跟随系统位数[AppDataFolder]当前用户漫游数据目录[CommonAppDataFolder]所有用户共享数据目录,写配置缓存常用这个[ProductName][Manufacturer][ProductVersion]取自产品信息页[APPDIR]应用程序文件夹的完整路径,自定义动作里引用主目录时用它
把文件拖进应用程序文件夹之后,右键任意一个可执行文件,可以直接创建快捷方式。快捷方式的“目录”填[ProgramMenuFolder]就是开始菜单,填[DesktopFolder]就是桌面。注意别把快捷方式建在“应用程序文件夹”里,那是把 .lnk 塞进安装目录,卸载时能删掉但用户根本看不到。
64 位程序有个专门的坑:默认组件被标记为 32 位,装到 64 位系统上会被重定向到Program Files (x86)。要装进真正的Program Files,需要把组件属性里的 64 位标志勾上,同时目录属性换成[ProgramFiles64Folder]。这一步没做对,程序装完能运行,但读取同目录的配置文件时会跑到另一个位置去,排查起来相当费劲。
3.3 注册表、文件关联与卸载信息
注册表页按树形结构编辑,写进去的内容会随卸载自动清除,前提是写在安装时创建的键下。手工写HKEY_LOCAL_MACHINE\SOFTWARE\[Manufacturer]\[ProductName]是最省事的做法,卸载时整个子树一起走。
写注册表时有两点要注意。第一,值的数据类型别选错,字符串和扩展字符串(可展开的)在注册表编辑器里看着一样,行为完全不同,路径里带环境变量时必须用扩展字符串。第二,卸载时的清理只针对“这个组件负责的键值”,如果你在安装后由程序自己往这个键下写了数据,卸载能清掉;但如果程序写到别的产品键下,就要靠自定义动作收拾。
文件关联在专门页面配置,填扩展名、关联的可执行文件、图标和描述即可。日常交付里最常漏的是“打开方式”里的显示名,不填的话用户在右键菜单里看到的是一串程序名,观感很差。
3.4 用命令行把构建拉进流水线
界面点构建适合调试,正式发布要走命令行,才能塞进自动化流程。工具自带一个命令行入口,装在 bin 目录下。
# 工程路径和输出目录都避免中文与空格 AI_CLI="C:/Program Files (x86)/Advanced Installer 15.2/bin/x86/AdvancedInstaller.com" PROJ="D:/build/MyApp/MyApp.aip" # /build 增量构建,/rebuild 强制全量重建(改了资源文件后用这个) "$AI_CLI" /rebuild "$PROJ" # 构建完成后检查产物是否生成以及时间戳 ls -l "D:/build/MyApp/Setup/MyApp.msi"/build会复用上次的中间产物,速度快但改了汉化资源、图标这类外部文件时可能不生效,发布前一律用/rebuild。命令行的返回码要接住,非 0 就让流水线直接失败,别让一个构建失败的包流到测试环节。
批量出多个配置时,用脚本循环调用就行:
$cli = "C:\Program Files (x86)\Advanced Installer 15.2\bin\x86\AdvancedInstaller.com" $jobs = @( @{ Proj = "D:\build\MyApp\MyApp.aip"; Cfg = "Release" }, @{ Proj = "D:\build\MyApp\MyApp.aip"; Cfg = "Debug" } ) foreach ($j in $jobs) { Write-Host "开始构建 $($j.Cfg) ..." & $cli /rebuild $j.Proj if ($LASTEXITCODE -ne 0) { throw "构建失败: $($j.Cfg),退出码 $LASTEXITCODE" } }$LASTEXITCODE是判断成败的唯一依据,别靠肉眼看有没有生成文件。$jobs里的配置名要和工程内构建配置页里定义的名字一致,写错了命令行不会报“配置不存在”,而是安静地按默认配置出一个包,这类问题在流水线里极难发现。
4. 升级、卸载与自定义动作:三个最容易翻车的环节
装得上不算本事,升得动、卸得干净才算。这一章的三个点,是实际交付里返工率最高的地方。
4.1 升级码、产品码、版本号:三件套的配合关系
这三个东西的关系必须先捋清楚,否则升级一定出问题。
升级码是产品家族的身份证,同一个软件的所有版本共用一个,永远不改。产品码是每一个具体版本的身份证,每次发布新版本都要重新生成,绝不能复用。版本号决定谁新谁旧,前三位参与比较,第四位只是内部标记。
正确的发布流程是:改版本号 → 重新生成产品码 → 升级码保持不动 → 构建。三步里错一步,结果分别是:
- 升级码改了:新版本被当成另一个软件,装完变成两个程序并存,用户桌面出现两个图标。
- 产品码没换:安装程序认为“这个产品已经装了”,直接走维护模式,新文件根本没进去,用户反馈“装了跟没装一样”。
- 版本号没加:升级规则判定新版本不比旧版本高,静默跳过。
升级规则在专门的升级页配置。加一条规则,检测方式选升级码匹配,动作选“安装新版本并卸载旧版本”。有条件的话把“只允许降级到指定版本以下”这种限制也配上,防止误操作把高版本刷成低版本。
顺带说一个容易被忽略的点:如果旧版本在目标机上装的是“每用户”模式,新版本改成“每机器”模式,升级会失败,因为两者的安装上下文不一致。这种模式在工程建立时就定死了,后期改不了,只能卸载重装。选型时想清楚,是给单用户装还是给整机所有用户装。
4.2 自定义动作:时机差一步,结果差一个世界
自定义动作用来干那些标准安装流程覆盖不到的事:初始化数据库、注册服务、写配置文件、清理残留。功能很强,时机选错就是灾难。
常用的执行时机按发生顺序排:安装初始化 → 安装校验 → 复制文件 → 安装收尾。区别在于:
- 放在“复制文件”之前,此时程序文件还没落地,任何依赖主程序的脚本都会失败。
- 放在“复制文件”之后、“安装收尾”之前,是最常用的位置,文件已就位、还没写卸载信息。
- 放在“安装收尾”之后,属于提交阶段,回滚已经不可用,这里的失败会导致卸载不干净。
还有一个维度是执行上下文。同步执行在主流程里跑,失败能触发回滚;延迟执行在独立进程里跑,权限更高但失败不回滚。需要管理员权限又需要回滚的操作,常见做法是拆成两段:校验逻辑放同步,实际操作放延迟,用属性传参。
执行条件决定这个动作在什么场景下跑,最常用的三个:
| 条件表达式 | 含义 | 典型用途 |
|---|---|---|
NOT Installed | 首次安装 | 初始化配置文件 |
Installed | 已安装(维护/升级) | 保留用户数据 |
REMOVE="ALL" | 完全卸载 | 清理自建目录 |
条件写错是静默失败的根源。动作没执行、也没报错,日志里翻半天才发现条件恒为假。判断方法是在详细日志里搜动作名,看它的执行记录是被跳过还是被调用。
部署自定义动作之前,我一般会先在干净虚拟机上跑三遍:全新安装、覆盖升级、完全卸载,三遍都看日志确认动作被执行了。跳过验证这步,到了客户现场才暴露,返工成本至少翻三倍。
4.3 静默安装参数:MSI 和 EXE 引导包是两套
给运维批量部署的包必须支持静默安装。MSI 和 EXE 引导包的参数不通用,写错了会弹出一个没人点的界面卡在那里,定时任务超时之后整个批次全挂。
MSI 走系统自带的安装引擎:
# 静默安装,同时输出详细日志,失败时靠日志定位 msiexec /i "D:\pkg\MyApp.msi" /qn /norestart /l*v "D:\log\install.log" # 静默卸载,产品码从日志或注册表卸载项里取 msiexec /x "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" /qn /norestart /l*v "D:\log\uninstall.log"/qn是完全无界面,/qb是只有进度条,/norestart阻止安装完自动重启(这条一定要加,否则半夜批量部署能把一整批机器全重启了)。/l*v输出最详细的日志,星号表示全部信息,排查时是第一手资料。
EXE 引导包有自己的一套参数:
# 外层引导程序静默,内层 MSI 也静默 MyApp.exe /exenoui /qn /norestart /l*v "D:\log\boot.log" # 想看到基本进度界面,把 /exenoui 换成 /exebasicui MyApp.exe /exebasicui /qn /norestart/exenoui关掉引导程序的界面,/exebasicui只保留一条进度条。这两个开关控制的是外层,内层的/qn仍然要传,很多人只写了一个,结果静默了外层、内层照样弹窗。
卸载 EXE 引导包时注意,它的卸载入口和 MSI 不同,通常要带上/uninstall之类的参数,或者干脆走控制面板的卸载项调用内部 MSI 的产品码。批量脚本里最稳的做法是读注册表卸载项里的UninstallString,直接执行那串命令,不自己拼参数。
5. 避坑指南:汉化版五个高频翻车现场
这一章的五条全是现象、原因、解决三段式,都是实际遇到过、能复现的。
第一条:界面一半中文一半英文,个别对话框还是全英文。
现象是主界面菜单中文了,但新建工程向导、错误提示框仍然是英文,甚至有的对话框一片空白。原因是汉化资源只覆盖了主程序的资源文件,向导用的对话框模板是另一批资源,补丁包没包含;如果包是从别的小版本移植过来的,资源 ID 对不上,加载就会失败。
解决分两步:先核对汉化包说明里对应的具体小版本号,版本不一致就别硬用;再从安装目录的 Languages 子目录里确认中文资源文件确实存在且大小正常(0 字节说明拷贝被拦截了)。如果确实只有主程序被汉化,日常使用可以接受,但别指望向导也是中文,团队内部要提前说清楚。
第二条:构建报“找不到文件”,但文件明明在。
现象是点构建之后进度条卡在复制文件阶段,日志里提示某个源文件无法访问。八成是路径里带中文或空格,老版本在处理工程内的相对路径时对非 ASCII 字符支持不彻底。
解决是把工程文件、源文件目录、输出目录三处全部挪到纯英文无空格的路径下,比如统一放D:\build\xxx\。挪完记得在工程里重新指定一次文件路径,光挪文件不重新引用是无效的,工程里存的还是旧的绝对路径。
第三条:客户机上装到一半失败,提示缺少运行库。
现象是安装程序启动后弹窗说缺少某个框架版本,点确定就退出。原因是纯 MSI 包不会带前置依赖,目标机环境不满足就直接失败。这类问题的日志里通常能看到 1603,但真正的原因在更早的几行。
解决有两条路:一是把包改成 EXE 引导方式,在引导程序的前置条件页里加上运行库检测和安装;二是在部署脚本里先跑一遍环境检查。对外交付一律走第一条,因为客户环境不可控。内部批量分发可以走第二条,运维脚本里加个判断就行。
第四条:升级完变成两个程序并存。
现象是新版本装上去了,旧版本还在,控制面板里出现两条记录,桌面两个图标。基本可以断定是升级码在生产过程中被改过,或者新版本的升级规则没有正确匹配到旧版本。
解决是回到旧版本的工程文件,把升级码原样复制到新版本工程里,升级码一旦确定就不再改动。已经出现并存的机器,先用旧版本的产品码静默卸载,再装新版本。产品码可以从注册表的卸载项里查到,别自己猜。
第五条:汉化后程序启动报错,提示资源加载失败。
现象是覆盖汉化资源之后主程序打不开,报一个资源相关的异常。原因通常是覆盖了不匹配版本的文件,或者覆盖过程中把某个文件截断了(安全软件拦截常见)。
解决是把备份的 Languages 目录整个还原回去,确认程序能正常启动,再重新走一次覆盖流程。这次覆盖之前先关闭安全软件实时防护,覆盖完做哈希比对,全部一致再启动。回退这件事一定要在覆盖前就准备好,事后补救往往已经找不到原始文件了。
6. 交付前的最后一公里:用日志和差分把包钉死
包做出来不等于能交付。真正决定成败的是交付前那套验证动作,这一章给三个能直接抄的方法。
6.1 从详细日志里把 1603 扒出来
1603 是安装失败最笼统的错误码,本身没有信息量,价值全在日志上下文里。打开日志之后不要从头读,直接搜关键字。常用的搜索词是Return value 3,安装引擎在每个动作失败时都会打这一行,往上翻十几行就是失败的具体动作名和返回码。另一个高频词是Note: 1: 2262,代表某个自定义动作抛了异常。
读日志的顺序建议是:先搜Return value 3找到失败点,再往上找这个动作的入参(比如它要访问的路径、要写的注册表键),最后对照目标机的实际状态确认差异。大部分失败追到底是三类:权限不够、路径不存在、前置依赖缺失。
日志文件会比较大,几万行很常见。用 PowerShell 快速捞失败段落比人工翻快得多:
# 从 MSI 详细日志中提取失败动作及其上下文 $log = "D:\log\install.log" $lines = Get-Content $log for ($i = 0; $i -lt $lines.Count; $i++) { if ($lines[$i] -match "Return value 3") { # 向上回溯 15 行,定位是哪个动作失败的 $start = [Math]::Max(0, $i - 15) Write-Host "===== 失败点(行 $i)=====" -ForegroundColor Red $lines[$start..$i] | ForEach-Object { Write-Host $_ } } }$i - 15这个回溯窗口是经验值,多数情况下失败动作名就在这十几行内。窗口太小会漏掉动作名,太大则输出一堆无关信息。找到动作名之后,再去工程里对照这个动作的配置,比盲猜快得多。
6.2 装前装后做一次注册表与文件差分
“卸不干净”这个问题靠肉眼永远查不出来,必须做差分。方法是装之前导一份注册表和文件清单,卸载之后再导一份,比对差异。
# 安装前快照 $snap = "D:\snap" New-Item -ItemType Directory -Path $snap -Force | Out-Null reg export "HKLM\SOFTWARE" "$snap\reg_before.reg" /y Get-ChildItem "C:\Program Files (x86)" -Recurse -ErrorAction SilentlyContinue | Select-Object FullName, Length, LastWriteTime | Export-Csv "$snap\files_before.csv" -NoTypeInformation -Encoding UTF8 # 此处执行安装 + 卸载,然后导第二份 reg export "HKLM\SOFTWARE" "$snap\reg_after.reg" /y Get-ChildItem "C:\Program Files (x86)" -Recurse -ErrorAction SilentlyContinue | Select-Object FullName, Length, LastWriteTime | Export-Csv "$snap\files_after.csv" -NoTypeInformation -Encoding UTF8 # 比对:仅存在于卸载后的条目,就是残留 Compare-Object (Get-Content "$snap\reg_before.reg") (Get-Content "$snap\reg_after.reg") | Where-Object SideIndicator -eq "=>" | Select-Object -First 50SideIndicator为=>表示只在第二份(卸载后)里出现,也就是残留。-First 50是为了先看前 50 条,实际残留可能上百条,重点看那些带产品名前缀的键。
这套方法配合干净虚拟机用。每轮验证前把虚拟机恢复到快照,装一次、卸一次、比一次,三轮下来基本能把隐藏残留全挖出来。文件差分同理,只是比对的是 CSV 里的路径集合。
6.3 直接在包里读属性,确认构建产物没错
最后一个技巧:交付前别只看文件生成了,直接读 MSI 里的属性表,确认产品码、升级码、版本号、语言这些关键字段都对。
# 读取 MSI 属性表,核对关键字段 $msi = "D:\pkg\MyApp.msi" $installer = New-Object -ComObject WindowsInstaller.Installer $db = $installer.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $null, $installer, @($msi, 0)) $view = $db.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $db, @("SELECT Property, Value FROM Property")) $view.GetType().InvokeMember("Execute", "InvokeMethod", $null, $view, $null) while ($true) { $rec = $view.GetType().InvokeMember("Fetch", "InvokeMethod", $null, $view, $null) if ($null -eq $rec) { break } $name = $rec.GetType().InvokeMember("StringData", "GetProperty", $null, $rec, @(1)) $value = $rec.GetType().InvokeMember("StringData", "GetProperty", $null, $rec, @(2)) if ($name -in @("ProductCode","UpgradeCode","ProductVersion","ProductLanguage","ProductName")) { "{0,-16} = {1}" -f $name, $value } }这段用 COM 接口读属性表,StringData的 1 和 2 分别是第一列和第二列的索引。只输出白名单里的五个字段,避免刷屏。核对重点:升级码应该和上一个版本完全一致,产品码应该是全新的,版本号比上一版高。这三项在自动化流水线里做成断言,能挡住 90% 的低级发布事故。
从那以后我每次出包,都强制走一遍“读属性表 → 干净机装一遍 → 卸一遍做差分”这套流程,哪怕只是改了一个图标。打包这件事,出错的代价从来不在制作环节,在客户现场。希望帮到你。
本文还有配套的精品资源,点击获取