资讯动态

Inno Setup 打包实战:从中文语言包到自动化出包

发布时间:2026/9/20 2:07:01 来源:尧图企业网站定制
1. 为什么桌面软件分发绕不开 Inno Setup做 Windows 桌面工具开发的人迟早会撞上同一个问题代码写完了怎么把它变成一个双击就能装、装完就能用、卸载还干净的安装包。我最早是用压缩包加一个 bat 脚本糊弄过去的用户拿到手先解压再手动改配置出了问题还得远程帮人排查。后来换过几个方案最后稳定在 Inno Setup 上一用就是好几年。Inno Setup 是一个专门做 Windows 安装程序的开源工具核心产物是一个.exe安装包。它的定位很清晰不追求花哨的界面而是把安装、卸载、注册表写入、快捷方式创建、开机自启、文件关联这些事做扎实。对于独立开发者、小团队内部工具、企业内部分发场景来说它几乎是性价比最高的选择。你不需要买商业打包软件的授权也不需要为了一个安装包去学 WiX 那套 XML 语法。这篇内容适合三类人第一类是刚写完第一个桌面程序、完全没打过包的新手第二类是打过包但被中文乱码、路径问题、静默安装折腾过的开发者第三类是想把打包流程接进 CI、实现一键出包的人。我会从下载安装讲到中文语言包配置再讲到脚本编写和自动化出包中间穿插我自己踩过的坑。你跟着走一遍基本能覆盖日常 90% 的打包需求。需要先说明一点Inno Setup 本身只负责打包和安装逻辑它不负责编译你的程序。也就是说你得先用你的开发工具把程序编译成 exe 或者一整套文件再交给 Inno Setup 去封装。这个边界搞清楚后面很多问题就不会困惑了。2. 下载安装与版本选择别一上来就装最新版2.1 官方渠道与版本差异Inno Setup 的官方发布渠道是 jrsoftware 的官网下载页提供两个主要版本一个是稳定版Stable Release一个是预发布版Pre-release。我的建议很直接生产环境一律用稳定版别碰预发布版。预发布版虽然会带一些新特性但偶尔会有脚本解析行为的变化你辛苦调好的脚本可能因为一个版本升级就报错。目前主流使用的是 Inno Setup 6 系列相比 5.x 有几个明显变化支持了更现代的 Windows 版本、改进了 Unicode 处理、编译器本身的界面也更新了。如果你维护的是老项目脚本里用了大量 5.x 时代的写法升级到 6 之前最好先备份脚本跑一遍编译看看有没有警告。下载的时候注意区分 32 位和 64 位安装器。现在基本都用 64 位系统了直接下对应的即可。安装过程没什么坑一路下一步就行但有两个选项值得留意是否安装 IDECompil32这个必须装后面写脚本、编译、调试都靠它。是否关联 .iss 文件建议勾上这样双击.iss脚本文件会直接用 Inno Setup 编译器打开省事。2.2 安装目录与权限的隐藏坑安装路径默认在C:\Program Files (x86)\Inno Setup 6。这里有个很多人忽略的点如果你打算把打包流程做成自动化脚本并且脚本里要调用ISCC.exe命令行编译器那么路径里带空格和括号会让命令行调用变得麻烦。我的做法是装到一个简单路径比如C:\InnoSetup6这样在批处理或者 CI 配置里写路径时不用反复处理引号转义。另一个坑是权限。Inno Setup 编译器本身不需要管理员权限就能运行但它生成的安装包在安装时如果涉及写入Program Files或者注册表HKEY_LOCAL_MACHINE就需要管理员权限。这个权限是在脚本里通过PrivilegesRequired控制的不是编译器决定的。很多人第一次打包发现装到一半报拒绝访问就是因为脚本里没声明需要提权而安装目录又选了系统保护目录。提示如果你只是做个人工具、装到用户目录下可以把PrivilegesRequired设为lowest这样安装时不会弹 UAC用户体验更好。但代价是不能写系统级注册表和公共目录。2.3 验证安装是否成功装完之后打开 Compil32新建一个空白脚本直接点编译。如果能在输出目录看到一个.exe生成说明环境没问题。这一步看着多余但能帮你排除掉安装包损坏杀毒软件拦截这类低级问题。我遇到过某台机器上杀软把 ISCC 当成可疑程序编译直接失败后来加了白名单才正常。3. 中文语言包让安装界面说人话3.1 默认界面为什么是英文Inno Setup 自带的语言文件里默认只加载英文。安装向导的按钮、提示、错误信息全是英文对于面向国内用户的软件来说体验很差。解决办法是引入中文语言包。官方仓库里其实已经包含了简体中文的语言文件文件名类似ChineseSimplified.isl但默认不启用需要你在脚本里显式声明。这里要区分两个概念安装界面语言和你的程序界面语言。Inno Setup 的中文语言包只影响安装向导本身不影响你打包进去的程序。很多人第一次配置完发现安装界面是中文了但我的软件还是英文这是两码事程序的语言得在程序内部处理。3.2 引入中文语言包的两种方式第一种方式是在脚本的[Languages]段里直接引用官方语言文件[Languages] Name: chinesesimplified; MessagesFile: compiler:Languages\ChineseSimplified.isl这里的compiler:是一个内置前缀指向 Inno Setup 安装目录。这样写的好处是不用把语言文件复制到项目里编译器会自动去安装目录找。第二种方式是把.isl文件复制到你的项目目录然后用相对路径引用[Languages] Name: chinesesimplified; MessagesFile: ChineseSimplified.isl这种方式适合团队协作因为语言文件跟着项目走别人拉下代码就能编译不依赖本机安装目录里有没有这个文件。我一般用第二种尤其是项目要进版本管理的时候。如果你需要同时支持中英文可以写两行[Languages] Name: english; MessagesFile: compiler:Default.isl Name: chinesesimplified; MessagesFile: ChineseSimplified.isl安装时用户可以在向导第一步选择语言。注意顺序第一行是默认语言。3.3 中文乱码的根因与修复中文乱码是 Inno Setup 打包里最高频的问题没有之一。表现有两种一种是安装界面上的中文变成问号或方块另一种是安装完成后程序读取的配置文件里中文乱码。第一种情况的根因通常是脚本文件本身的编码不对。Inno Setup 6 的编译器对脚本编码有要求.iss文件必须保存为带 BOM 的 UTF-8或者 ANSI。如果你用某些编辑器保存成了无 BOM 的 UTF-8中文就会出问题。我的习惯是统一用 UTF-8 with BOM在 VS Code 里右下角能直接切换。第二种情况更隐蔽往往不是 Inno Setup 的锅而是你的程序在读写文件时用了系统默认编码。比如安装脚本往配置文件里写了一段中文程序用 GBK 去读自然乱码。解决办法是统一编码要么全用 UTF-8要么全用系统 ANSI。我倾向于全 UTF-8然后在程序里显式指定编码。还有一个细节[Messages]段可以覆盖语言包里的具体条目。如果你觉得官方翻译某个词不贴切可以这样改[Messages] chinesesimplified.ButtonNext下一步 chinesesimplified.ButtonCancel取消这种覆盖方式在需要定制品牌话术时很有用比如把安装改成部署。4. 从零写一个能用的打包脚本4.1 脚本骨架与各段职责一个完整的.iss脚本由若干段Section组成每段用方括号开头。常用的段有这些段名作用[Setup]全局配置如程序名、版本、安装目录、输出路径[Files]声明要打包进安装包的文件[Icons]创建快捷方式、开始菜单项[Run]安装完成后执行的动作如启动程序[Tasks]可选任务如创建桌面快捷方式[Registry]写入注册表[Code]Pascal 脚本处理复杂逻辑先看一个最小可用的[Setup]段[Setup] AppName我的工具 AppVersion1.0.0 DefaultDirName{autopf}\MyTool DefaultGroupNameMyTool OutputDiroutput OutputBaseFilenameMyTool_Setup_1.0.0 Compressionlzma2 SolidCompressionyes PrivilegesRequiredlowest这里几个参数值得展开说。DefaultDirName里的{autopf}是一个常量会自动解析成Program Files或Program Files (x86)取决于系统架构和权限设置。如果你写死C:\Program Files\MyTool在 32 位系统或者没有权限的账户上就会出问题。用常量是更稳的做法。Compressionlzma2配合SolidCompressionyes能显著减小安装包体积代价是编译时间变长。对于几十兆以内的程序这个代价可以接受。如果打包的是几百兆的资源文件可以考虑关掉 solid 压缩换取更快的编译速度。OutputBaseFilename建议带上版本号这样每次出包不会互相覆盖也方便追溯。4.2 文件收集与目录结构映射[Files]段是打包的核心决定了哪些文件进包、进包后放在哪。基本写法[Files] Source: build\MyTool.exe; DestDir: {app}; Flags: ignoreversion Source: build\config\*; DestDir: {app}\config; Flags: ignoreversion recursesubdirs Source: docs\readme.txt; DestDir: {app}\docs; Flags: ignoreversionSource是编译机上的路径DestDir是安装后的目标路径{app}代表用户选择的安装目录。Flags里最常用的是ignoreversion意思是覆盖已存在的文件不做版本比较。如果你不加这个标志安装程序发现目标文件版本更新时会跳过导致更新失败。recursesubdirs用于递归复制子目录配合通配符*使用。注意Source里的路径是相对于.iss文件所在目录的不是相对于当前工作目录。这个细节在自动化脚本里特别重要因为 CI 环境的工作目录可能和脚本目录不一致。还有一个实用标志是excludes可以排除某些文件Source: build\*; DestDir: {app}; Flags: ignoreversion recursesubdirs; Excludes: *.pdb,*.log这样能把调试符号和日志排除掉减小包体积。4.3 快捷方式、开机自启与文件关联[Icons]段负责创建快捷方式[Icons] Name: {group}\我的工具; Filename: {app}\MyTool.exe Name: {autodesktop}\我的工具; Filename: {app}\MyTool.exe; Tasks: desktopicon{group}是开始菜单文件夹{autodesktop}是桌面。第二行末尾的Tasks: desktopicon表示这个快捷方式只在用户勾选了对应任务时才创建。对应的[Tasks]段[Tasks] Name: desktopicon; Description: 创建桌面快捷方式; GroupDescription: 附加任务:这样安装向导里会出现一个复选框用户自己决定要不要桌面图标。默认勾选可以加Flags: checkedonce。开机自启通过注册表实现[Registry] Root: HKCU; Subkey: Software\Microsoft\Windows\CurrentVersion\Run; ValueType: string; ValueName: MyTool; ValueData: {app}\MyTool.exe; Flags: uninsdeletevalue用HKCU而不是HKLM这样不需要管理员权限。uninsdeletevalue保证卸载时自动清理这个键值不留垃圾。文件关联稍微复杂一点需要同时写注册表和刷新图标缓存[Registry] Root: HKCR; Subkey: .mytool; ValueType: string; ValueData: MyTool.Document; Flags: uninsdeletekey Root: HKCR; Subkey: MyTool.Document\shell\open\command; ValueType: string; ValueData: {app}\MyTool.exe %1注意ValueData里的引号转义路径带空格时必须用双引号包起来否则打开文件会失败。4.4 安装完成后的动作与卸载清理[Run]段控制安装完成后干什么[Run] Filename: {app}\MyTool.exe; Description: 立即运行我的工具; Flags: nowait postinstall skipifsilentpostinstall表示在安装向导最后一页显示这个选项skipifsilent表示静默安装时不执行。这两个标志配合使用能兼顾交互安装和自动化部署两种场景。卸载清理主要靠[UninstallDelete]段[UninstallDelete] Type: filesandordirs; Name: {app}\logs Type: filesandordirs; Name: {app}\cache程序运行时产生的日志和缓存安装包本身不知道需要显式声明卸载时删除。否则用户卸载完发现目录还在体验很差。5. 自动化打包把出包接进流水线5.1 命令行编译器的调用方式Inno Setup 的图形界面适合调试但自动化必须用命令行编译器ISCC.exe。基本调用C:\InnoSetup6\ISCC.exe path\to\script.iss如果脚本里用了相对路径建议先切换到脚本目录再调用或者用/D参数传入变量C:\InnoSetup6\ISCC.exe /DMyVersion1.2.3 script.iss脚本里用{#MyVersion}引用这个变量。这样版本号可以从外部注入不用每次改脚本。编译成功返回 0失败返回非 0。在 CI 里判断返回码就能知道出包是否成功。输出信息里会包含生成的安装包路径可以解析出来做后续上传。5.2 用批处理串起编译与打包一个典型的本地自动化脚本长这样echo off setlocal set VERSION1.0.0 set BUILD_DIRbuild set OUTPUT_DIRoutput echo [1/3] 编译程序... call build.bat if errorlevel 1 exit /b 1 echo [2/3] 打包安装程序... C:\InnoSetup6\ISCC.exe /DMyVersion%VERSION% installer\setup.iss if errorlevel 1 exit /b 1 echo [3/3] 完成输出在 %OUTPUT_DIR% endlocal这个脚本把编译程序和打包安装包两步串起来任何一步失败就中断。实际项目里build.bat可能是调用 MSBuild、dotnet publish 或者 PyInstaller。5.3 在 CI 中出包的注意事项把打包放进 CI比如 GitHub Actions、GitLab CI时有几个坑我踩过第一Inno Setup 不是默认安装的。CI 环境里需要先下载安装或者用预装了 Inno Setup 的镜像。安装时用静默参数/VERYSILENT /SUPPRESSMSGBOXES /NORESTART否则会卡在安装向导。第二路径分隔符和引号。CI 的 shell 可能是 bash调用 Windows 的 exe 时路径要用双引号包起来反斜杠要转义或者用正斜杠。我一般统一用正斜杠Windows 也能识别。第三输出产物要显式声明为 artifact否则 CI 跑完就丢了。以 GitHub Actions 为例- name: Build Installer run: ISCC.exe installer/setup.iss - name: Upload Artifact uses: actions/upload-artifactv3 with: name: installer path: output/*.exe第四版本号注入。CI 里通常用 git tag 或者构建号作为版本通过/D参数传给 ISCC避免手动改脚本。5.4 静默安装与批量部署企业内部分发时经常需要静默安装。Inno Setup 生成的安装包支持这些参数参数作用/SILENT静默安装显示进度条/VERYSILENT完全静默不显示任何界面/DIR路径指定安装目录/NORESTART禁止自动重启/LOG文件输出安装日志批量部署时配合组策略或者运维工具推送用/VERYSILENT /DIRC:\Tools\MyTool /LOGC:\temp\install.log就能无人值守完成。日志文件在排查安装失败时非常有用能看到每一步的执行结果。注意静默安装时[Run]段里带skipifsilent标志的动作不会执行。如果你希望静默安装后也启动程序要去掉这个标志但要评估是否真的需要。6. 那些年我踩过的打包坑6.1 路径含空格导致的启动失败最经典的一个坑程序装到C:\Program Files\MyTool快捷方式能创建但双击没反应。排查半天发现是[Run]段里启动程序的路径没加引号系统把C:\Program当成了可执行文件。修复方式就是给路径加双引号在 Inno Setup 脚本里用两个双引号转义Filename: {app}\MyTool.exe这个坑在文件关联、开机自启的注册表项里同样存在凡是路径可能带空格的地方都要加引号。6.2 覆盖安装时的文件占用程序正在运行时执行覆盖安装会提示文件被占用无法写入。Inno Setup 默认的处理是让用户关闭程序但有时候用户不知道怎么关。可以在[Setup]段加CloseApplicationsyes让安装程序自动尝试关闭相关进程[Setup] CloseApplicationsyes RestartApplicationsnoCloseApplications会检测哪些文件被占用并尝试关闭对应进程。RestartApplications控制安装完成后是否自动重启这些程序。这个功能依赖 Windows 的重启管理器对大部分程序有效但对某些后台服务可能无效。6.3 卸载残留的注册表与目录卸载不干净是用户投诉的重灾区。常见残留有三类程序运行时写的注册表、用户数据目录、日志文件。注册表残留可以在[Registry]段加uninsdeletekey或uninsdeletevalue标志自动清理。用户数据目录如果不在安装目录下需要在[UninstallDelete]里显式声明。还有一个隐蔽的{userappdata}下的配置。很多程序把配置存在这里卸载时不会自动删。我的做法是在[Code]段里写卸载钩子或者干脆在程序里提供清除所有数据的选项让用户自己决定。6.4 中文路径下的编译失败如果你的项目路径里有中文比如D:\项目\打包Inno Setup 编译时可能报找不到文件。根因是编译器对非 ASCII 路径的处理不够健壮。解决办法很简单项目路径全用英文。这个建议听起来土但能省掉大量莫名其妙的报错。CI 环境更是如此路径里带中文几乎必出问题。6.5 杀毒软件误报自己打的安装包被 Windows Defender 或者第三方杀软报毒这个很常见。原因通常是安装包没有数字签名加上 Inno Setup 生成的 exe 结构被某些启发式引擎判定为可疑。彻底解决需要买代码签名证书对安装包和主程序都签名。如果暂时没预算可以先把安装包提交给微软做误报申诉或者引导用户加白名单。这不是 Inno Setup 的问题是所有自签名安装包的通病。7. 让安装包更专业的几个进阶技巧7.1 自定义安装向导界面Inno Setup 支持通过[Code]段和WizardForm对象定制界面。比如在欢迎页加一段说明文字procedure InitializeWizard(); begin WizardForm.WelcomeLabel2.Caption : 本向导将引导你完成我的工具的安装。 #13#10 建议关闭其他程序后再继续。; end;#13#10是换行符。这种方式可以改标题、改按钮文字、加自定义页面。更复杂的定制需要创建TInputQueryWizardPage或者TInputOptionWizardPage用来收集用户输入比如服务器地址、授权码等。7.2 安装前环境检查有些程序依赖特定的运行库比如 .NET Runtime 或者 VC Redistributable。可以在[Code]段的InitializeSetup里检查function InitializeSetup(): Boolean; var Version: String; begin Result : True; if not RegQueryStringValue(HKLM, SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full, Version, Version) then begin if MsgBox(未检测到 .NET Framework 4.x是否继续安装, mbConfirmation, MB_YESNO) IDNO then Result : False; end; end;这样能在安装前给用户明确提示而不是装完运行时报错。检查逻辑可以根据实际依赖调整。7.3 多架构与多版本管理如果你的程序有 32 位和 64 位两个版本可以用同一个脚本配合条件编译[Setup] ArchitecturesInstallIn64BitModex64 [Files] Source: build\x86\MyTool.exe; DestDir: {app}; Flags: ignoreversion; Check: not Is64BitInstallMode Source: build\x64\MyTool.exe; DestDir: {app}; Flags: ignoreversion; Check: Is64BitInstallModeCheck参数决定这条规则是否生效。这样一份脚本能同时处理两种架构安装时自动选择对应文件。7.4 版本号与更新检测安装包里带上版本号程序启动时可以读取自身版本和服务器上的最新版本比对提示用户更新。版本号在[Setup]段的AppVersion里定义程序可以通过读取注册表或者文件版本信息获取。我一般用文件版本信息因为编译时可以直接从构建脚本注入不用改 Inno Setup 脚本。[Setup] VersionInfoVersion{#MyVersion}配合/DMyVersion1.2.3传入这样安装包属性里显示的版本和实际版本一致方便用户和管理员核对。8. 关于打包这件事的一些个人体会打包这件事技术含量不算高但细节极多而且每个细节都直接影响用户体验。我见过太多功能做得不错的工具因为安装包做得粗糙用户第一印象就打了折扣。Inno Setup 的好处是它把这些细节都暴露给你你可以控制每一个环节代价是你得花时间理解它。我的建议是第一次打包不要追求一步到位。先跑通最小流程能装、能启动、能卸载。然后再逐步加中文、加快捷方式、加自启、加自动化。每加一个功能就测一遍别攒到最后一起调否则出了问题很难定位是哪一步引入的。另外打包脚本一定要进版本管理。.iss文件是纯文本diff 起来很清楚谁改了什么一目了然。语言文件、图标、许可证文本这些资源也一起放进去保证任何人拉下代码都能编译出一样的安装包。最后说一个容易被忽略的点测试。安装包至少要在三种环境下测过——干净的全新系统、已经装过旧版本的系统、没有管理员权限的普通账户。这三种场景覆盖了绝大多数真实情况能提前发现权限、覆盖安装、残留清理的问题。我自己就因为在干净系统上没测漏掉了一个运行库依赖用户装完打不开返工了一次。打包不是开发的终点而是交付的起点。把它做扎实用户拿到手的第一分钟就会觉得这东西靠谱。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价