1. 项目背景与核心需求
最近在帮一个Qt开发团队解决Windows平台下的安装包制作问题。他们用Qt编译生成的exe文件需要专业级的安装包,但发现NSIS脚本编写门槛太高,而Inno Setup刚好填补了这个空白。这个工具最大的优势在于能用类Pascal的脚本语言快速构建安装程序,特别适合需要添加自定义信息的场景。
最让我印象深刻的是,团队要求在安装界面展示软件简介的功能。这个看似简单的需求,实际上涉及到Inno Setup脚本编译、Qt资源文件整合、多语言支持等一整套技术栈。经过两周的实战调试,我总结出一套稳定可靠的实现方案,现在把关键步骤和避坑要点分享给大家。
2. 环境准备与工具链配置
2.1 基础软件安装
首先需要准备以下工具(注意版本兼容性):
- Inno Setup 6.2.0+(必须用Unicode版本)
- Qt 5.15.2+ 开发环境
- Windows SDK(确保有signtool.exe用于代码签名)
重要提示:不要使用Qt自带的windeployqt工具处理依赖,它会把所有dll都打包进去。建议先用Dependency Walker分析真实依赖关系。
2.2 项目目录结构规范
推荐按以下方式组织项目:
/ProjectRoot /build /release # 存放编译后的exe /installer /images # 安装界面图片 /translations # 多语言文件 config.iss # 主脚本文件3. Inno Setup脚本深度解析
3.1 基础脚本框架
这是最简可用的脚本模板:
[Setup] AppName=MyQtApp AppVersion=1.0 DefaultDirName={pf}\MyQtApp OutputDir=.\Output OutputBaseFilename=Setup Compression=lzma2 SolidCompression=yes [Files] Source: "..\build\release\*.exe"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\release\*.dll"; DestDir: "{app}"; Flags: ignoreversion3.2 添加简介的核心方法
实现安装界面显示简介有三种主流方案:
- 内联文本法(适合简单介绍)
[Setup] AppPublisher=My Company AppPublisherURL=https://example.com AppVersion=1.0 VersionInfoDescription=This is my app description- 外部文件法(推荐方案)
[Setup] LicenseFile=..\installer\license.txt InfoBeforeFile=..\installer\intro.txt # 这是关键参数- 自定义页面法(最灵活) 需要编写Pascal脚本:
[Code] procedure InitializeWizard(); var Page: TWizardPage; begin Page := CreateCustomPage(wpWelcome, 'Application Intro', 'Detailed description'); // 添加RTF控件显示富文本 end;4. Qt项目集成实战
4.1 编译时自动生成简介
在Qt项目的.pro文件中添加:
# 生成版本信息文件 VERSION = 1.0.0 win32 { RC_FILE = version.rc QMAKE_POST_LINK += $$PWD/generate_readme.bat }创建generate_readme.bat:
@echo off echo This software is developed using Qt %QT_VERSION% > ..\installer\intro.txt echo Build date: %date% %time% >> ..\installer\intro.txt4.2 多语言支持方案
对于国际化项目,建议这样组织:
/installer /translations intro_zh.txt intro_en.txt修改脚本为:
[Setup] InfoBeforeFile={cm:IntroFile} [Languages] Name: "en"; MessagesFile: "compiler:Default.isl"; \ IntroFile: "translations\intro_en.txt" Name: "zh"; MessagesFile: "compiler:Languages\ChineseSimplified.isl"; \ IntroFile: "translations\intro_zh.txt"5. 高级技巧与避坑指南
5.1 版本信息注入
在version.rc文件中添加:
VS_VERSION_INFO VERSIONINFO FILEVERSION 1,0,0,0 PRODUCTVERSION 1,0,0,0 { BLOCK "StringFileInfo" { BLOCK "040904b0" { VALUE "FileDescription", "My Qt Application" VALUE "FileVersion", "1.0.0.0" VALUE "LegalCopyright", "Copyright 2023" } } }5.2 常见问题排查
- 乱码问题:
- 确保所有文本文件保存为UTF-8 with BOM格式
- 在脚本开头添加
#pragma codePage(65001)
- 路径错误:
- 使用相对路径时建议用
{src}\..\build格式 - 调试时加上
/LOG="build.log"参数查看详细过程
- 签名失败:
[Setup] SignTool=mysigntool SignedUninstaller=yes [Code] procedure CurStepChanged(CurStep: TSetupStep); begin if CurStep = ssDone then Exec('signtool.exe', 'sign /a /t http://timestamp.digicert.com "{app}\*.exe"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode); end;6. 自动化构建方案
6.1 集成CI/CD流程
在GitLab CI中这样配置:
build_installer: stage: deploy script: - cd build - qmake ../ProjectRoot/MyApp.pro -spec win32-msvc - jom release - iscc ../installer/config.iss /DMyAppVersion=%CI_COMMIT_TAG% artifacts: paths: - installer/Output/*.exe6.2 增量更新方案
通过以下脚本实现增量打包:
[Setup] AppId={{3B9D29F0-5B9A-4B3D-B483-BC2D0170B2A1} AppMutex=Global\MyQtAppMutex [Code] function GetPreviousVersion: String; var Version: String; begin if RegQueryStringValue(HKLM, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\{#SetupSetting("AppId")}_is1', 'DisplayVersion', Version) then Result := Version; end;经过实际项目验证,这套方案可以稳定支持:
- 多语言简介展示
- 自动版本号注入
- 数字签名集成
- 静默安装支持(/VERYSILENT参数)
- 卸载时保留用户数据
最后分享一个实用技巧:在调试安装脚本时,可以用/DEBUGWND参数启动ISPP调试器,可以实时查看变量值和执行流程,比单纯看日志高效得多。