简介Advanced Installer 20.7.1 是一款面向软件开发者、系统集成商与运维人员的 Windows 安装包制作工具能够生成符合 MS Windows 认证要求的 MSI 安装包。其图形用户界面直观简洁支持自定义欢迎页、安装过程页面、许可协议与对话框样式方便用户根据产品品牌进行界面定制。该压缩包共含 2000 个文件压缩后大小约 161.36 MB文件构成以 png、jpg、ico 等界面图标与背景图片为主同时包含 aip 工程文件、xsd 配置定义、rtf/xml 说明文档以及少量 msi 成品示例。这种结构大体还原了实际高级安装工程的项目布局从视觉素材到安装规则配置均有涉及还可看到中英文界面文件与多类辅助脚本。已有 940 人学习下载对于希望快速上手 Advanced Installer、掌握 MSI 封装流程或搭建规范安装包模板的用户这套资源提供了即开即用的样例与配置参考能有效减少从零摸索的时间。1. Advanced Installer 20.7.1软件打包工具先搞清楚它解决什么问题Advanced Installer 20.7.1是一款面向Windows平台的软件打包工具最擅长的场景是“应用写完了却交不出去”——客户要一个双击能装的EXE、运维要一个能静默分发的MSI、升级时还得保住用户配置和注册表数据。它的价值是把程序文件、运行库依赖、服务、注册表、快捷方式这些散件整合成标准安装包而不必像WiX那样对着底层表结构写XML。适合谁Windows桌面软件、企业内部系统、硬件配套软件的开发者和交付工程师。不适合谁只做Linux发布、应用完全走应用商店自动更新的团队。技术团队里常把它和InstallShield、WiX放在一起比较实际用下来它最接近“画界面就能生成专业安装包”的那一类同时保留命令行构建CI也能接。2. 选型与安装为什么是Advanced Installer而不是InstallShield或WiX安装包工具选错后面换一次等于把所有升级链路重做一遍所以开头值得多花点时间。2.1 选型对比InstallShield、WiX、Advanced Installer差在哪对比维度InstallShieldWiXAdvanced Installer上手成本高术语密集新成员培训周期长高需要理解MSI表结构中向导和可视化面板为主配置方式半界面半脚本纯XML工程文件GUI为主底子是XML工程MSIX/AppX支持支持但配置偏重需要额外扩展内置打包和转换向导命令行自动化可用但脚本繁琐天然适合编译链提供AdvancedInstaller.comGit协作工程文件结构复杂合并困难文本XML适合Git.aip是XML可合并但有冲突点典型团队大型企业安装包团队有MSI底层功底的研发中小研发团队、独立交付这个结论不是凭空对比是实际项目里踩过的。InstallShield的问题是“会的人很贵不会的人学不动”做一个包往往卡在少数人身上。WiX的问题是编译和链接阶段太慢改一个安装路径要在XML里翻三处新人容易改错节点。Advanced Installer落在中间日常配置在界面里完成出了问题又能直接看底层MSI日志不会被工具缚住手脚。2.2 安装与评估模式先确认授权再开始建项目安装过程本身不复杂管理员账号运行安装程序即可。有两个实际问题值得注意杀毒软件可能拦截安装过程中注册的动态库放行一次就好安装完成后建议先打开一次软件让首次运行初始化完成再开始建项目否则首次创建项目时会卡在初始化过程。首次启动一般会进入评估模式。评估模式能正常建项目、构建安装包但生成的包会带试用提示不能用于正式交付。团队里常有“用评估版做了两周最后要发版才发现限制”的情况这是最容易避免的翻车点。确认手上有没有正式授权比调任何参数都优先。新建项目时模板选择也影响后续路线。默认向导里我会选“MSI项目”而不是“简单项目”。MSI项目自带卸载入口、修复机制、按机器或按用户安装的完整能力简单项目更像一个壳适合演示不适合做产品级交付。后续所有配置都围绕“生成标准MSI”这个目标展开。2.3 项目属性先锁三样Product Name、Version、Upgrade Code打开项目属性Project Properties面板第一步不是拖文件是先把三个字段定下来。Product Name是显示在Windows“程序和功能”里的名字客户和IT管理员看到的就是它。不要把内部代号填进去我之前就把一个项目代号发出去了客户那边的资产清单对不上来来回回查了一下午。Version是版本号这里有个容易错的地方MSI版本只识别前三位填1.0.0.1时系统里显示的是1.0.0第四位被忽略。版本比较、升级判断都只以前三位为准。Upgrade Code是升级链路的“身份证”在整个产品生命周期里都不要改。项目创建时工具会自动生成一个GUID我习惯把这个GUID复制到Git仓库里的一个固定文件中比如docs/product-identity.md每次改版本都对照一下。如果有人不小心点了“重新生成GUID”所有老客户都会变成新装升级链路彻底断掉这是比改错版本号更隐蔽的坑。还要顺手定一下Install Scope企业分发选per machine配合管理员权限安装个人小工具可以选per user。这个选项影响注册表写入位置、服务运行身份和卸载权限后期再改会牵连一串路径所以开头就要定死。2.4 先构建一次空项目把环境问题排除在配置问题之前正式填充文件之前我通常先构建一次空项目只配置Product Name和Version不加任何文件。目的是验证授权状态、构建工具链、输出目录三项是否正常。构建按钮在Builds面板输出目录设置成一个稳定路径例如D:\build\out。第一次构建看到生成的app.msi和app.exe就说明环境没问题。之后再出问题都是配置层面的排查范围小很多。这里能看到一个常见细节同一配置可以同时产出MSI和EXE。EXE本质是一个引导程序把MSI包在壳里用户双击EXE时引导器自动触发MSI安装流程。企业场景里大家更愿意给客户EXE但内部批量部署时用MSI加静默参数所以两种产物一起产出最省事。3. 把应用装进安装包文件、注册表、服务与快捷方式的落地配置这一章是安装包的核心内容95%的交付问题都出在这里的配置细节上。3.1 Files and Folders同步源目录别手动拖文件见过有同事把几十个文件一个个拖进安装目录树下个版本加了一个DLL漏拖上线当晚客户报错。后来换成“同步文件夹”的方式再也没有出现过“漏文件”这种低级问题。在Files and Folders面板里把整个发布目录映射为安装目录下的一个文件夹。比如应用程序发布在bin\Release下就在安装树里建一个AppFolder把bin\Release整个映射过去。之后每次构建自动同步源目录新加的文件自动进包删掉的文件自动从包中去除。维护的是源目录本身不是安装内容的清单人工遗漏的概率大幅下降。目标文件夹字段要用默认的AppFolder属性不要写死C:\Program Files\MyApp。用户安装时可能会选其他路径写死路径会让“选择安装目录”这一步失效在64位系统上还可能出现路径重定向文件去了意想不到的位置。文件安装这部分的原则很简单用属性引用目录别用绝对路径。3.2 注册表写入时机、位数和Wow6432Node的坑注册表在Registry面板配置。常见写入位置有两个HKCU\Software\产品名存放用户级配置HKLM\Software\产品名存放机器级配置。两者要对应Install Scope的选择per user安装写HKCUper machine安装写HKLM。最隐蔽的问题是32位和64位视图。64位系统上32位程序写HKLM\Software会被系统重定向到HKLM\Software\Wow6432Node。如果安装包同时带32位和64位组件注册表值要按真实位数分开配置否则程序运行起来读不到自己的配置。判断方法很简单在目标机器上用regedit查一下实际写入位置再对照程序读取的逻辑。这一条属于典型的“装完不报错但程序行为不对劲”的疑难问题。写入时机也要注意。有一类注册表项必须在卸载时移除比如文件关联另一类应该保留比如用户偏好设置。MSI的注册表配置默认跟着组件管理走安装写入、卸载删除。想让某个键值跨版本保留不能写在注册表面板里要在应用首次启动时自己创建否则升级卸载旧版时就被清掉了。3.3 服务、快捷方式与启动条件三个容易忽略的字段服务配置在Services面板。添加服务后需要填写服务名、可执行文件路径、启动类型。服务路径必须用[AppFolder]这样的属性引用不要手打C:\Program Files\MyApp\MyApp.exe原因和文件目录一样用户改了安装路径服务就指向了一个不存在的位置。服务设为自动启动时MSI会在安装结束时尝试启动它。如果启动失败安装不会自动回滚但会留下一个禁用状态的服务用户看到安装成功服务却是死的。验证方法安装完成后马上执行net start 服务名确保返回正在启动。快捷方式面板里最容易漏的是“工作目录”字段。不填的话用户双击快捷方式时工作目录是system32程序里所有相对路径都会读错文件。至少要填[AppFolder]这样双击时工作目录和程序目录一致。启动条件也是必配项最常见的是检查.NET运行时版本。这里的判断逻辑容易变成玄学检测到版本号满足条件程序启动还是报缺运行库。根源往往是检测的是“运行库安装值”而不是实际生效的运行时版本。我的建议是条件写保守一点检测主版本不要锁次版本避免一个补丁版本差异就挡住整批客户。3.4 运行库依赖Prerequisites比往目录塞DLL更可靠.NET和VC运行库是Windows桌面应用最常见的依赖。Advanced Installer提供Prerequisites机制把对应Redistributable加进安装包安装时先装依赖再装主程序。不要用“文件复制”的方式把整个.NET运行时目录塞进安装目录。这样做表面能跑但系统更新和Windows Update不会主动修复这些目录里的运行时文件版本会一直卡在打包那一刻安全补丁也打不进去。正确做法是让Redistributable进入系统常规的安装位置由系统自身管理版本。处理运行库依赖有个判断标准在干净的虚拟机里只装系统补丁不装开发环境然后安装你的包。能跑说明依赖齐全不能跑说明缺依赖或版本策略太激进。很多“我机器上正常客户机器上报错”的问题都是在这个环节漏了。4. 升级与补丁方案从1.0到2.0不丢数据也不丢配置安装包的第一版往往容易升级链路才是真正拉开差距的地方。4.1 Upgrade Code和ProductCode升级的“身份证”到底指谁MSI的升级判断基于三样东西Upgrade Code、版本号、语言。Upgrade Code标识产品家族ProductCode标识具体版本。同一个产品的不同版本Upgrade Code必须一致ProductCode必须不同。升级时要避免两类错一是Upgrade Code变了新包被当作独立产品客户机器上出现两个同名应用二是同一版本的包ProductCode不一致导致批量部署时旧的“程序和功能”条目没被正确替换。正确做法是同一个版本的MSI固定用同一个ProductCode版本递增时才生成新的。在实际项目里我见过最头疼的情况是“升级后用户配置全部丢失”。查下来往往是升级策略配置成了“先卸载旧版再装新版”卸载时把MSI组件跟踪的数据文件删掉了。要区分用户数据如果是应用运行时创建的不受MSI卸载影响如果一开始就放在Files and Folders里就会被卸载一起清掉。所以用户数据目录不要通过安装包分发应用首次启动时自动生成是最稳的。4.2 三种构建产物MSI、EXE、MST各在什么场景用一个安装配置可以产出多种格式。MSI是标准安装包支持msiexec静默参数、组策略分发、批量部署工具是企业环境的根基。EXE是引导包适合给不懂技术的最终用户双击安装。MST是转换文件配合msiexec /t在分发时覆盖属性同一份MSI可以适配不同部门的不同安装路径或配置。日常交付产线通常同时出MSI和EXE给客户的下载链接放EXE给IT管理员的目录放MSI。MST只有在“一个安装包要按部门差异化部署”时才用得上普通项目可以先不碰。构建面板里还能产出补丁包它记录两个版本之间的增量差异体积小走网络分发快。但补丁包只能从固定基线版本上升级如果客户机器上有多个版本散落补丁链会变得非常难维护。面向内部系统时我倾向于用完整MSI做版本升级除非网络带宽真的限制到KB级否则不建议依赖补丁来做主力升级通道。4.3 多版本管理尽量用完整MSI升级补丁包只留少数基线升级方案在设计阶段就要想清楚“从哪些版本能升上来”。常见策略是允许从上一个发布版本升级客户跨度太大时强制先装最新基线再升级避免一条升级链覆盖太多版本组合。版本号策略我建议用三段式主版本.次版本.修订号。主版本和次版本决定功能边界修订号用于修复。MSI对第四段忽略所以不用费心维护四位版本号。每次发版时记录Version、ProductCode、Upgrade Code三个值到发布清单下次构建前对照确保没有意外变化。4.4 MSIX边界新分发可以迁传统服务型软件别硬搬20.7.1这一版对MSIX的支持已经比较成熟。MSIX适合新软件开发例如.NET Core/WinUI类应用沙箱运行、自动更新、应用商店分发都很顺手。但MSIX不适合以下场景程序需要安装Windows服务常驻后台需要写系统级驱动需要和外部老DLL深度耦合。这些能力在MSIX容器里会被限制硬迁移会产生大量运行时不兼容问题。传统WinForms加服务的软件留在MSI体系里更可靠至少升级、卸载、服务管理都是成熟路径。选型上有个简单的判断标准应用是否能接受“以用户身份运行在容器内”能接受MSIX值得投入必须用系统服务或驱动继续用MSI别折腾。5. 构建、验证与避坑记录五条踩坑现象和它们的真实原因安装包做得成不成功不是看构建是否通过而是看安装、卸载、升级三个动作在干净机器上是否都正确。5.1 verbose日志msiexec /l*v 打开后看哪几行遇到安装失败第一步不是猜是拿详细日志msiexec /i D:\build\out\MyApp-1.0.0.msi /qb /l*v C:\logs\myapp_install.log参数含义/i指定安装包/qb显示基础进度界面/l*v输出详细日志。日志生成后搜Return value 3或Installation failed找第一个出现错误码的位置那通常就是失败根因。不要拉到最后看总结MSI日志的失败原因一定藏在路径操作或属性赋值失败的上下文里。下面几个MSI返回值值得记在脑子里返回值含义常见原因0安装成功无1603致命错误访问权限、系统策略拦截1619安装包无法打开路径无效或文件损坏3010成功但需重启文件被占用或系统组件更新3010是唯一一种“成功但需要重启”的情况批量部署时要特殊处理否则后续步骤会踩在未重启的系统上。5.2 静默安装与卸载企业分发前必须跑通的命令企业环境里安装包必须支持静默安装msiexec /i D:\build\out\MyApp-1.0.0.msi /qn /l*v C:\logs\silent_install.log INSTALLDIRC:\Program Files\MyApp/nq表示不显示用户界面全程静默。INSTALLDIR可以覆盖安装路径但要看项目属性里该属性是否允许公共修改有些项目把它设成私有命令行传了也不生效。静默安装最怕UAC弹窗。如果命令从一个普通用户Shell发起UAC弹窗会挂在那边没人点安装进程一直等待。验证方式是从非管理员Shell执行一遍这条命令确认它不会停在某个隐藏窗口上。批量分发工具一般以系统身份运行问题不大但手动测试时要注意这一点。卸载测试同样要跑msiexec /x {PRODUCT-GUID} /qn /l*v C:\logs\uninstall.logPRODUCT-GUID可以在项目构建信息里查到。卸载完成后要检查三处安装目录是否清空、“程序和功能”是否移除条目、服务是否停止。这三处有一处残留都说明卸载逻辑有问题不能发版。5.3 五条踩坑记录现象、原因、解决第一条64位机器上安装后程序跑到SysWOW64目录找文件。现象是程序能启动但实际读取的目录不是预期路径。原因是MSI目标平台没选x64构建时还停留在x86。解决方法是到构建面板把目标平台设为x64或x86分别对应不要用Neutral然后重新构建并在64位机器上复测。第二条升级后“程序和功能”里出现两个同名应用。现象是最新版本装完旧版本还列在列表里。原因是新包的Upgrade Code与旧包不一致MSI判定为两个独立产品。解决方法是把旧版本的Upgrade Code找出来填进新项目的对应字段升级测试要在真机完整跑一遍“1.0升到2.0”。第三条卸载后用户配置被清空。现象是卸载干净了但用户下次装回来时配置全没了。原因是用户数据目录被误认为MSI组件内容安装时由包创建卸载时被包回收。解决方法是安装包只分发程序文件和默认模板用户数据由应用首次启动时生成到AppData或ProgramData不纳入MSI跟踪范围。第四条杀毒软件把安装包隔离。现象是构建出来的EXE在部分机器上被拦截。原因是引导型EXE的行为特征容易和捆绑器混淆尤其在没有数字签名时。解决方法是正式发布使用有代码签名的MSI和EXE发版前用杀毒引擎扫一遍必要时提交厂商做白名单。第五条批量静默安装返回码0但程序实际没有装上。现象是部署平台显示成功目标机器上没有可执行文件。原因是检查脚本只看退出码而MSI在某种情况下退出码为0但安装被系统策略跳过。解决方法是安装后检查关键文件或注册表值不要只信退出码同时在日志里搜Could not access或ShellExecuteEx定位被跳过的那一步。6. 自动化打包与冒烟验证把Advanced Installer接进CI的最后一公里6.1 命令行构建AdvancedInstaller.com接入CIAdvanced Installer安装目录下自带AdvancedInstaller.com这是命令行构建入口。CI里我习惯这样调用$advinst Get-ChildItem C:\Program Files*\Caphyon\Advanced Installer\bin\x64\AdvancedInstaller.com -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1 if (-not $advinst) { throw AdvancedInstaller.com not found } $advinst.FullName /build .\installer\MyApp.aip -builds MSI -outdir .\output\release if ($LASTEXITCODE -ne 0) { throw build failed with code $LASTEXITCODE }这段脚本用Get-ChildItem自动定位不同版本号路径下的命令行工具避免把安装路径写死。单个CI节点上不会装多个版本所以取第一个找到的就够。日志文件路径加入CI系统的归档目录构建失败时能直接拉出MSI日志定位。版本号不建议在CI里用脚本改.aip的XML节点这个XML结构会随版本微调正则替换早晚踩坑。更稳的做法是在GUI里为CI单独建一个构建配置版本号固定在该配置中发版时手动改配置属性CI只负责按配置名构建。6.2 三项冒烟装得上、升得动、卸得净构建产物出来最后一道关是冒烟测试。我在干净虚拟机或隔离环境跑下面这个脚本$version git describe --tags --abbrev0 $version $version.TrimStart(v) $msi .\output\release\MyApp-$version.msi Start-Process msiexec -ArgumentList /i $msi /qn /l*v .\output\smoke.log -Wait if (-not (Test-Path C:\Program Files\MyApp\MyApp.exe)) { throw install smoke failed } Start-Process msiexec -ArgumentList /x $msi /qn /l*v .\output\uninstall.log -Wait if (Test-Path C:\Program Files\MyApp\MyApp.exe) { throw uninstall smoke failed } Write-Host SMOKE PASSED $version用Start-Process -Wait保证msiexec完全结束后再检查文件系统不要立刻轮询。卸载验证不要用Win32_Product查询它会触发系统一致性检查拖慢执行。文件存在性检查比写一堆状态判断可靠得多。我现在的固定习惯是每次Release合并前拉一台干净Windows虚拟机跑一遍这个冒烟脚本。版本对不上或卸载残留会当场红掉这十几分钟能拦住大多数“到客户那边才发现装不上”的尴尬。希望帮到你。本文还有配套的精品资源点击获取