简介Advanced Installer 22.5 是专业的 Windows 安装包制作工具本资源正是围绕该版本整理的完整安装与项目文件包面向需要在本地部署、学习或维护安装包制作环境的开发者与运维人员。包内共2000个文件压缩后约229.56MB其中以 aip 项目模板、png/jpg/ico 界面与图标素材、xml/xsd 配置定义、msi/exe 安装程序、rtf/html 文档及多语言界面资源为主覆盖从图形界面定制、快捷方式与注册表配置、静默安装脚本到最终产出安装包的常见环节同时包含一定数量的 bmp/svg/xaml 视觉资源、cfg/aitemplate 配置与模板、ps1/cmd 辅助脚本等目录结构清晰便于按需检索复用。已有1428人学习下载对于希望离线搭建 Advanced Installer 环境或需要参考标准打包流程、复用默认模板与素材的开发者而言这份资源能帮助快速理解安装包结构与配置逻辑减少重复配置工作。1. Advanced Installer 22.5 打包 Windows 安装包先想清楚它替你解决了什么被安装包反复折磨过的人应该都经历过这个场景交付一个带 Windows 服务的小工具压缩包发过去对方解压后双击 exe 没反应注册表里多出几个不知道谁写的键卸载时更是删不干净。换了 Advanced Installer 22.5 之后这些问题大部分不再是玄学——它把散装的 exe、dll、配置文件、Windows 服务和注册表项统一编排成标准 MSI 或引导型 EXE 安装包装的时候走 Windows Installer 引擎卸的时候按记录回滚。这篇文章面向手里拿着 Windows 桌面程序的开发、运维或技术支持人员讲清楚这个工具怎么用、参数怎么设、以及我在实际出包时踩进去又爬出来的坑。2. 建工程前先选型MSI、EXE 引导包与 MSIX 的边界打开 Advanced Installer 22.5第一屏不是让你填产品名而是选 Project Type。很多人在这里凭感觉点了一个后面才发现装进域环境费劲、命令行静默装不了、升级策略对不上。选型这事值得先说透。2.1 三种工程类型怎么选只看第一个安装场景就足够我见过一个团队把内部小工具打成 MSIX结果分发时要额外配置 App Installer签名的坑还绕着走了两周。拿来做对比三种格式的边界其实很清晰类型适用场景命令行控制对系统环境要求门槛MSI企业内部工具、需要组策略分发、需要精确卸载记录完整支持 msiexec 参数仅要求 Windows Installer 服务正常低EXEBootstrapper需要把多个安装包串起来、要自定义品牌界面依赖引导器怎么封装通常兼容性最好中MSIX面向商店/企业托管平台有强沙箱与签名要求有限需要较新 Windows部署链路较长高我一般默认选 MSI。原因是它把安装台账交给 Windows Installer 管理用户中途取消、安装失败、卸载残留这些事引擎都有记录。Advanced Installer 的 EXE 引导包在我的场景里只用来做两段式安装外层 EXE 先检测 .NET 运行库或者 JDK缺了就装依赖再调用内层 MSI。这样既能享受 MSI 的记账能力又能替用户把前置依赖解决掉。这里有个容易犯的毛病把 EXE 理解成「从文件夹里拷出来打个包就叫 exe」的自解压程序。自解压只是把文件放出来什么都不写进系统台账卸载时只能靠遍历目录删文件。Advanced Installer 的 EXE 是 Bootstrapper二选一时先问自己目标机器上是否缺前置运行库不需要就 MSI需要再用 EXE 包一层。2.2 从空白工程到能跑的 MSI必须改的三个属性新建工程时选「Simple」模板22.5 会生成一个最小 MSI 工程。左侧栏从上到下是 Products、Media、Files and Folders、Shortcuts、Registry、Services 这几类页面整个打包逻辑就是告诉它「文件放哪、注册表写哪个根、服务叫什么名、快捷方式建哪儿」。建完工程先改三个地方缺一个后面都会翻车第一步打开 Product Details 页面把 Product Name、Manufacturer、Product Version 填对。Product Version 是四位点分版本号首位不能超过 255。这不是 Advanced Installer 的限制是 Windows Installer 的版本规则写成 256.1.0 会在构建时报版本号非法。Product Code 这一栏让工具自己生成即可它是这个安装实例的唯一身份。但 Upgrade Code 需要慎重一个产品线从头到尾保持同一个 Upgrade Code后面做大版本升级才能被识别为「旧版本」。如果每个迭代都重新随机生成 Upgrade CodeMSI 就认定这是两个不相干的产品升级时旧版本不会被处理。安装类型选 per-machine 还是 per-user内部工具一律 per-machine装在 Program Files 下对机器上所有用户可见per-user 装进 %LOCALAPPDATA%同一台机器另一个账号登录就要重装一次。验证配置没问题直接 Build。构建完的 MSI 默认在 Output 目录里。我习惯先把目标机器恢复到干净状态再手工验证一次安装。2.3 用 msiexec 验证第一次构建静默参数与完整日志图形界面双击安装只是验证了「能弹窗」验证不了无人值守场景。我每次构建完必跑一条静默安装命令顺手把日志抓全msiexec /i myapp.msi /qn /l*v install.log/i表示安装/qn是完全静默不弹任何窗口/l*v是输出详细日志到 install.log。*代表 verbose 级别v代表带详细信息。这条命令执行完退出码 0 表示安装成功其他值都能在日志里找到失败点。装完再验证卸载msiexec /x myapp.msi /qn /l*v uninstall.log这里有个细节MSI 卸载时也会跑一遍日志而且卸载日志比安装日志更容易暴露问题比如组件忘记注册、文件解锁失败。把这两个命令放进自己的验证清单比在图形界面点十遍 Next 都管用。注意如果目标机器上曾经装过同名但不同 ProductCode 的版本卸载命令必须指定具体产品代码否则 msiexec 会提示找不到产品。需要时用msiexec /x {GUID}精确卸载。3. 把文件、注册表和 Windows 服务装进去三块最常翻车的配置3.1 文件目录安装路径用 INSTALLDIR 还是默认目录在 Files and Folders 面板里工程会预置一个 Application Folder默认映射到[ProgramFilesFolder][Manufacturer][ProductName]。绝大多数情况下这个路径可以直接用理由是企业内部工具不需要给用户选择安装目录的权利固定路径反而方便后续维护和脚本引用。如果你确实需要让用户自定义安装目录做法是选中 Application Folder在属性面板里重定义 INSTALLDIR 属性再在 UI 对话框里加一个目录选择框。这里我要提醒一个最常见的坑用户改了安装路径但你的服务配置和快捷方式参数里写死了绝对路径安装完服务起不来。凡是引用安装目录的地方全部要用[INSTALLDIR]这个属性占位而不是硬编码路径。文件级联也要注意。把一个版本的程序文件夹整体拖进 Application Folder 时22.5 会保留原文件夹层级。如果里面混着 Debug 符号文件或者临时文件一起打进去会让安装包体积变大、卸载时多一堆无用的记录。我每次拖文件前先做一次目录清理砍掉 pdb、cache、日志这类运行时产物。关于权限per-machine 安装到 Program Files 时安装过程会触发 UAC 提升。写入 Program Files 下的文件默认没有修改权限这对大多数只读程序文件是对的。如果程序运行时要写配置到自己的安装目录请立刻停止这个设计——把配置放到 ProgramData 或 AppData避免权限边界问题。3.2 注册表HKLM 与 HKCU 的选择依据Registry 页面里可以按新建键值的方式添加注册表项。填表时有三个字段Root根键、Key路径、Name/Value名称和值。选 Root 的判断依据只有一条这个配置是机器级的还是用户级的。服务要读的连接串、进程要加载的全局开关放 HKLM 的SOFTWARE\YourCompany\YourApp纯界面偏好、最近打开文件这类个人设置放 HKCU。HKCU 的好处是卸载时跟随用户配置自动清理不需要额外逻辑HKLM 则必须靠 MSI 的组件记账来确保删除。Advanced Installer 里用 Registry 原生表配置卸载时 Windows Installer 会把安装时写的键值自动回滚掉。这是它比我之前习惯的「自定义动作里 reg add/reg delete」高明的地方——脚本删注册表一旦路径写错卸载就会往系统关键位置下手风险太大。有一类场景走原生表解决不了运行时才决定写哪个注册表路径。这时只能上自定义动作但自定义动作默认在系统上下文跑权限和路径变量都要自己处理好。我的原则是能用 Registry 面板表达的就用面板绝对不手写注册表脚本。3.3 Windows 服务启动类型、账户与「起不来」的根源带服务的程序安装包的核心难点全在服务配置上。在 Services 页面新建服务需要填这些字段配置项推荐值说明Service Name程序内部名称与代码里 OpenSCManager 用的名称一致Display Name中文/易读名称显示在 services.msc 里Start TypeAutomatic随系统启动内部工具普遍用自动启动Start AccountLocalSystem 或 NetworkService见下方分析Dependencies对应依赖服务名服务启动顺序依赖账户选择是起不来的第一大原因。LocalSystem 是本地最高权限能访问本地几乎所有资源但访问网络共享时是以机器身份出面域环境下会受限NetworkService 类似访问网络仍受 AD 策略管理专用域账户适合需要访问数据库、需要特定权限的服务但要把账户密码以参数方式传入安装包。服务起不来时第一件事不是回来调安装包而是去 Windows 事件查看器里翻 System 日志Source 写 Service Control Manager 的那几条就是答案。常见的两种情况服务路径写成了[INSTALLDIR]字面量没有解析成真实目录或者服务依赖的 dll 不在服务可搜索的路径里。前者检查服务 binPath后者检查 PATH 环境变量是否在安装时写入了。提示服务若依赖网络地址比如启动时要连数据库建议 Start Type 选 AutomaticDelayed Start。否则开机时网络栈没就绪服务启动直接超时再去看它已经是停止状态。3.4 快捷方式与文件关联装完能让用户找得到入口Shortcuts 页面把「桌面图标」「开始菜单图标」指向 Application Folder 里的主程序。这里有两个值得注意的点。第一桌面图标对企业批量部署往往是多余的却在卸载时又占一条记录我通常只建开始菜单快捷方式避免用户桌面被塞满。第二主程序是 32 位还是 64 位快捷方式的目标固定用[INSTALLDIR]属性不能因为当前测试机上路径一样就写成绝对路径。如果程序涉及打开特定扩展名的文件文件关联也是在 Shortcuts/Files Associations 里做。关联的默认动作命令同样用属性占位否则用户改了安装目录双击文件就会报「找不到程序」。4. 升级包比首版难十倍版本规则、Upgrade Code 与卸载回滚做首版安装包多数人半天就能跑通。真正检验对 MSI 理解深度的是第二版、第三版升级包。升级做不好旧文件残留、两个版本并排、卸载时互相打架全来了。4.1 小版本原地升级与大版本重装Product Code 和 Upgrade Code 的分工先把两个 GUID 的职责说清楚。Upgrade Code 是整个产品线的身份证永远不变Product Code 是当前这个安装实例的身份证大版本升级时可以变小版本升级时可以不变。在 Advanced Installer 的 Upgrades 页面里点 Add Upgrade配置新版本的版本号范围和升级策略。它会自动找目标机器上已安装的同 Upgrade Code 产品决定是原地覆盖还是先卸载再安装。升级场景Product CodeUpgrade Code结果小修小补保持相同不变原地覆盖保留用户配置大版本不兼容重新生成不变旧版记录替换装新版误改 Upgrade Code随意变了两个版本并存旧版卸载成谜我最开始做大版本升级时习惯性地把 Product Code 和 Upgrade Code 一起重新生成结果用户机器上出现「旧版还能从控制面板卸载新版也装上了」的奇观。从那以后我对 Upgrade Code 的态度是代码里定义一个常量构建脚本不生成它格式化也不许动。4.2 文件版本号与 REINSTALLMODE为什么升级完旧 dll 还在升级后目标机器目录里还有旧版 dll十有八九不是安装包没起作用而是文件版本规则把旧文件「保留保护」了。Windows Installer 在覆盖文件前会对比新文件版本、语言和哈希。新版文件版本号如果小于或等于已安装的版本引擎认定「没有需要更新的文件」跳过覆盖。解决办法是先检查自己的输出文件有没有正确写入 Assembly/File Version。很多开发机的构建流程里版本号写死在 csproj 或版本头文件里升级时忘了改打出来的 dll 还是旧版本号。文件版本改了仍然不覆盖再检查升级策略里的 REINSTALLMODE。我一般会在升级策略中显式设置REINSTALLMODEamusa强制覆盖所有文件m使用新版文件替换旧版u补齐缺失文件s校验哈希在 Advanced Installer 的 Upgrades 设置里把升级行为勾选为「Replace older version」再配合文件版本号递增旧文件残留的问题基本消失。注意 REINSTALLMODE 是 MSI 引擎级别的参数不是工具自定义的开关。4.3 卸载与回滚设计让 MSI 自己清算别手写删除逻辑卸载时哪些文件被删完全由组件Component记账决定。你在 Files and Folders 面板里安排的文件构建时被分配到一个组件卸载时组件计数归零就整体删除。明白这一点就不要在自定义动作里写「删除用户配置文件」的脚本。用户配置保留策略要做的是另一件事程序运行后把配置写在安装目录外的位置比如 ProgramData。卸载时 MSI 只清理装进 Program Files 的那部分运行数据保留是预期行为。如果你非要卸载时询问用户「是否保留配置」可以在卸载流程里加一个条件自定义动作弹一个 Message Box而不是直接把删除路径写死。安装失败的自动回滚也是 MSI 机制的一部分。安装到一半出错引擎会按逆向顺序撤销已完成的复制和注册表写入。这里要防的是「延迟提交型」自定义动作安装实际没成功但自定义动作已经把状态写进了系统环境变量回滚救不回来。我现在的原则是自定义动作只做安装主流程之外的事且必须允许失败不要把业务逻辑挂进安装事务里。5. 避坑实测记录装不上、服务起不来、旧文件残留的五条排查路径以下五条全是实打实遇到过的现场每条按现象、原因、解决三个步骤拆开。这些问题在官方文档里都找得到但真正出事时没人翻文档有份排查清单会快很多。5.1 现象一双击 MSI 没反应任务管理器里一闪而过双击后安装界面没出现任务管理器里 msiexec 进程闪一下就消失。原因可能是系统里已经有一个 MSI 安装事务在排队Windows Installer 全局串行前一个没结束后一个直接退出也可能是 SmartScreen 拦截但没弹提示。解决先看事件查看器的 Windows Installer 日志确认有没有 「Another installation is already in progress」再用命令行执行一遍msiexec /i myapp.msi /l*v install.log日志会直接把失败原因写清楚比盲改工程靠谱得多。5.2 现象二服务装上了启动那一栏是错误安装过程没有报错服务也注册进了 services.msc但启动按钮点下去马上失败。原因排查顺序第一看事件查看器里 Service Control Manager 的报错编号第二看服务的「登录」选项卡是不是用本机账户在跑第三确认 binPath 里的安装目录路径有没有解析正确。我遇到最多的是第三种——服务配置里写的路径带上了[INSTALLDIR]字面量安装时没有被替换成真实路径。解决在 Services 页面重新选择主程序文件作为服务可执行文件不要手打路径手打的路径构建时不会做属性解析。5.3 现象三升级完旧 DLL 还在安装目录用户跑完升级包检查安装目录发现旧版 dll 和配置文件还在。原因可能是文件版本号没递增Windows Installer 根据文件版本决定是否覆盖也可能是升级策略没有设成「替换旧版本」。解决先确认输出文件的版本号确实变了再按前面说的设置 REINSTALLMODEamus。文件版本号验证可以在 PowerShell 里跑(Get-Item .\myapp.dll).VersionInfo.FileVersion别靠文件名猜。5.4 现象四执行 msiexec 报图 1618 或「另一个安装正在执行」多台目标机器同时推安装包或者同一台机器上连续跑两个安装包就会遇到这个错。原因是 Windows Installer 的全局互斥同一时刻只允许一个安装事务。解决要么等上一个安装进程结束要么在分发工具里做队列串行。我在 CI 里出包后做安装验证时会先把可能残留的 msiexec 进程清干净再跑新的安装测试。5.5 现象五卸载后注册表里还能搜到产品路径控制面板卸载完注册表里依旧能找到产品名。这个现象要分情况看如果你在 HKLM 里写的键是 MSI 组件管理的卸载就会自动删如果你的自定义动作或程序安装后又往 HKLM 写了新键卸载时没人替它擦屁股。解决排查注册表里的残留键是谁写的原生表配置的交给 MSI程序运行时写的那部分要么在设计上改成 ProgramData 文件要么在卸载界面里提供「清理用户数据」选项让用户决定是否删除。6. 把 22.5 的构建从界面搬到命令行CI 出包脚本6.1 我留在 Jenkins 里的出包脚本图形界面构建适合开发期一到正式发布我坚持用命令行。Advanced Installer 提供了独立命令行工具 AdvancedInstaller.com位置在安装目录下。先确认构建机上这个文件存在并把它加进系统 PATH。只要 .aip 工程里已经把输出格式、输出目录、版本信息都配好命令行就只是触发一次构建AdvancedInstaller.com /build myapp.aip构建完后按退出码判断结果非零就是失败。需要临时改版本号时我用一个参数覆盖工程里的版本值这样 CI 里每次构建都能用日期或构建号当版本号不用手工改工程文件AdvancedInstaller.com /build myapp.aip -SetVersion 2.4.0不同小版本对命令行参数命名略有差别构建机上先跑一次AdvancedInstaller.com /?看头几行帮助确认当前版本的参数写法这一步每次升级工具版本后都要做。构建时如果弹出许可证激活窗口检查构建机有没有把许可证授权信息配置完整——CI 环境下最怕安装完工具后忘了输许可证导致自动化出包卡在人机交互上。我在 Jenkins 里把它做成一个 Pipeline 步骤构建产物按产品名加日期放到共享目录然后触发安装虚拟机做 msiexec 验证。从那以后每次出包我都强制走一遍「命令行构建 → 干净机器静默安装 → 查日志 → 升级测试 → 卸载测试」这个流程没有再手工点过下一步。如果你是第一次接触 22.5这五个环节可以先用图形界面跑通再逐步迁到命令行出包的节奏会稳很多。希望帮到你。本文还有配套的精品资源点击获取