前言

在现代软件开发中,专业的安装包是产品交付的重要环节。Inno Setup 作为一款免费的 Windows 安装包制作工具,以其强大的功能和灵活的配置受到广大开发者的喜爱。本文将详细介绍如何使用 Inno Setup 制作专业的安装包。
点击前往:Inno Setup 官网 点击下载:Inno Setup 中文包

第一章:Inno Setup 基础概念

1.1 什么是 Inno Setup?

Inno Setup 是一个免费的 Windows 安装程序制作工具,由 Jordan Russell 开发。它提供了丰富的功能,包括:

  • 创建单个 EXE 安装文件
  • 支持自定义安装界面
  • 强大的脚本语言支持
  • 完整的卸载功能支持

1.2 基本项目结构

一个典型的 Inno Setup 脚本文件(.iss)包含以下主要部分:

1
2
3
4
5
6
7
8
9
10
11
[Setup]           ; 安装程序基本设置
[Languages] ; 语言支持配置
[Types] ; 安装类型定义
[Components] ; 组件定义
[Files] ; 文件复制规则
[Run] ; 安装后运行程序
[Registry] ; 注册表操作
[UninstallRun] ; 卸载时运行程序
[UninstallDelete] ; 卸载时删除文件
[Icons] ; 快捷方式创建
[Code] ; Pascal 脚本代码

第二章:基础配置详解

2.1 [Setup] 段配置

这是安装程序的核心配置部分,定义了安装包的基本属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[Setup]
; 应用程序信息
AppName=我的应用程序
AppVersion=1.0.0
AppPublisher=我的公司
AppPublisherURL=https://www.mycompany.com/
; 安装目录设置
DefaultDirName={autopf}\MyApplication
; 允许用户修改安装目录
DisableDirPage=no
; 开始菜单文件夹名称
DefaultGroupName=我的应用程序
; 输出设置
OutputDir=Output
OutputBaseFilename=MyApp_Setup
SetupIconFile=myapp.ico
; 压缩设置
Compression=lzma2
SolidCompression=yes
; 权限设置
PrivilegesRequired=admin
WizardStyle=modern

关键参数说明:

  • AppName:应用程序名称
  • DefaultDirName:默认安装目录
  • {autopf}:自动选择 Program Files 目录
  • PrivilegesRequired=admin:需要管理员权限

2.2 多语言支持

前言有中文语言包下载链接,已挂载至github文仓

1
2
3
[Languages]
Name: "chinesesimp"; MessagesFile: "ChineseSimplified.isl"
Name: "english"; MessagesFile: "compiler:Default.isl"

第三章:安装类型与组件管理

3.1 定义安装类型

  • Flags: iscustom 表示自定义选项
1
2
3
4
[Types]
Name: "full"; Description: "完整安装"
Name: "compact"; Description: "典型安装"
Name: "custom"; Description: "自定义安装"; Flags: iscustom

3.2 组件定义

  • Types 表示分组依据
  • Flags: fixed 表示必选组件
1
2
3
4
5
[Components]
Name: "main"; Description: "主程序文件"; Types: full compact custom; Flags: fixed
Name: "database"; Description: "数据库组件"; Types: full
Name: "drivers"; Description: "驱动程序"; Types: full
Name: "docs"; Description: "帮助文档"; Types: full

第四章:文件处理与复制

4.1 [Files] 段配置

1
2
3
4
5
6
7
8
9
10
[Files]
; 基本文件复制
Source: "..\Build*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
; 组件相关文件
Source: "..\Database*"; DestDir: "{app}\Database"; Flags: ignoreversion; Components: database
Source: "..\Drivers*"; DestDir: "{app}\Drivers"; Flags: ignoreversion; Components: drivers
; 配置文件(不覆盖用户修改)
Source: "config.ini"; DestDir: "{app}"; Flags: ignoreversion onlyifdoesntexist
; 临时文件(安装后删除)
Source: "temp_setup.exe"; DestDir: "{tmp}"; Flags: deleteafterinstall

常用 Flags 说明:

  • ignoreversion:忽略文件版本检查
  • recursesubdirs:递归复制子目录
  • onlyifdoesntexist:仅当文件不存在时复制
  • deleteafterinstall:安装完成后删除

4.2 目录常量说明

常量 说明
{app} 应用程序安装目录
{tmp} 系统临时目录
{src} 安装文件所在目录
{pf} Program Files 目录
{cf} Common Files 目录

第五章:安装过程控制

5.1 运行外部程序

1
2
3
4
5
6
7
8
9
[Run]
; 安装后运行主程序
Filename: "{app}\MyApp.exe"; Description: "启动应用程序"; Flags: nowait postinstall skipifsilent
; 安装服务
Filename: "{app}\ServiceInstaller.exe"; Parameters: "/install"; StatusMsg: "正在安装服务..."; Flags: runhidden waituntilterminated
; 执行命令行操作
Filename: "net"; Parameters: "start MyService"; Flags: runhidden waituntilterminated
; 条件执行
Filename: "{app}\Tool.exe"; Parameters: "/setup"; Check: IsComponentSelected('tools')

5.2 注册表操作

1
2
3
4
5
6
7
[Registry]
; 添加文件关联
Root: HKCR; Subkey: ".myext"; ValueType: string; ValueName: ""; ValueData: "MyApp.Document"
; 应用程序设置
Root: HKCU; Subkey: "Software\MyCompany\MyApp"; ValueType: string; ValueName: "InstallPath"; ValueData: "{app}"
; 卸载信息
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Uninstall\MyApp"; ValueType: string; ValueName: "DisplayName"; ValueData: "我的应用程序"

第六章:数据库集成安装

6.1 MySQL 数据库安装示例

1
2
3
4
5
6
7
8
9
10
[Run]
; 停止现有服务
Filename: "net"; Parameters: "stop MySQL"; Flags: runhidden waituntilterminated
; 初始化数据目录
Filename: "{app}\mysql\bin\mysqld.exe"; Parameters: "--initialize-insecure --basedir=""{app}\mysql"" --datadir=""{app}\mysql\data"""; StatusMsg: "初始化数据库..."
; 安装并启动服务
Filename: "{app}\mysql\bin\mysqld.exe"; Parameters: "--install MySQLService"; Flags: runhidden waituntilterminated
Filename: "net"; Parameters: "start MySQLService"; Flags: runhidden waituntilterminated
; 执行SQL脚本
Filename: "{app}\mysql\bin\mysql.exe"; Parameters: "-u root -e ""source {app}\database\init.sql"""; Flags: runhidden waituntilterminated

6.2 ODBC 数据源配置

1
2
3
4
[Registry]
Root: HKLM; Subkey: "SOFTWARE\ODBC\ODBC.INI\MyAppDSN"; ValueType: string; ValueName: "Driver"; ValueData: "{app}\drivers\myodbc.dll"
Root: HKLM; Subkey: "SOFTWARE\ODBC\ODBC.INI\MyAppDSN"; ValueType: string; ValueName: "Server"; ValueData: "localhost"
Root: HKLM; Subkey: "SOFTWARE\ODBC\ODBC.INI\MyAppDSN"; ValueType: string; ValueName: "Database"; ValueData: "myappdb"

第七章:高级脚本编程

7.1 Pascal 脚本基础

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[Code]
// 自定义函数示例
function InitializeSetup(): Boolean;
begin
// 系统检查
if not IsWindowsVersionOrNewer(6, 1) then begin
MsgBox('此程序需要 Windows 7 或更高版本。', mbError, MB_OK);
Result := False;
end else begin
Result := True;
end;
end;
// 组件选择检查
function ShouldSkipPage(PageID: Integer): Boolean;
begin
// 如果未选择数据库组件,跳过数据库配置页面
if (PageID = wpSelectComponents) and not IsComponentSelected('database') then
Result := True
else
Result := False;
end;

7.2 服务状态检测函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
[Code]
// 检查服务是否已安装
function IsServiceInstalled(ServiceName: string): Boolean;
begin
Result := RegKeyExists(HKLM,
'SYSTEM\CurrentControlSet\Services'+ ServiceName);
end;
// 检查服务是否运行
function IsServiceRunning(ServiceName: string): Boolean;
var
ResultCode: Integer;
begin
Result := False;
if Exec(ExpandConstant('net.exe'), 'start', '', SW_HIDE,
ewWaitUntilTerminated, ResultCode) then
begin
// 解析 net start 输出判断服务状态
end;
end;
// 自定义安装页面
procedure CreateCustomPages;
var
Page: TWizardPage;
Edit: TEdit;
begin
Page := CreateCustomPage(wpSelectComponents, '数据库配置', '请输入数据库连接信息');
Edit := TEdit.Create(Page);
Edit.Parent := Page.Surface;
Edit.Left := ScaleX(0);
Edit.Top := ScaleY(0);
Edit.Width := ScaleX(200);
Edit.Text := 'localhost';
end;

第八章:卸载配置

8.1 卸载时执行操作

1
2
3
4
5
6
[UninstallRun]
; 停止并删除服务
Filename: "net"; Parameters: "stop MyService"; Flags: runhidden waituntilterminated
Filename: "{app}\ServiceInstaller.exe"; Parameters: "/uninstall"; Flags: runhidden waituntilterminated
; 删除临时文件
Filename: "{cmd}"; Parameters: "/c del /q ""{app}\temp*.*"""; Flags: runhidden waituntilterminated

8.2 卸载时清理文件

1
2
3
4
5
6
7
8
[UninstallDelete]
; 删除整个目录
Type: filesandordirs; Name: "{app}\temp"
Type: filesandordirs; Name: "{app}\logs"
; 删除特定文件
Type: files; Name: "{app}\cache.dat"
; 删除注册表项
Type: regkey; Root: HKCU; Subkey: "Software\MyApp"

第九章:快捷方式与用户界面

9.1 创建快捷方式

1
2
3
4
5
6
7
8
9
10
[Icons]
; 开始菜单快捷方式
Name: "{group}\我的应用程序"; Filename: "{app}\MyApp.exe"
Name: "{group}\卸载"; Filename: "{uninstallexe}"
; 桌面快捷方式
Name: "{autodesktop}\我的应用程序"; Filename: "{app}\MyApp.exe"
; 快速启动栏(Windows 7/8)
Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\我的应用程序"; Filename: "{app}\MyApp.exe"
; 带参数的快捷方式
Name: "{group}\配置工具"; Filename: "{app}\ConfigTool.exe"; Parameters: "-mode admin"

9.2 自定义安装界面

1
2
3
4
5
6
7
8
9
[Setup]
; 启用现代向导样式
WizardStyle=modern
; 自定义向导图片
WizardSmallImageFile=small.bmp
WizardImageFile=large.bmp
; 安装完成页面显示选项
DisableFinishedPage=no
DisableWelcomePage=no

第十章:实战案例 - 企业级应用部署

10.1 完整的企业应用安装脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[Setup]
AppName=企业管理系统
AppVersion=2.1.0
AppPublisher=企业信息科技有限公司
AppPublisherURL=https://www.example.com/
DefaultDirName={autopf}\EnterpriseSystem
DefaultGroupName=企业管理系统
OutputDir=Output
OutputBaseFilename=EnterpriseSystem_Setup
SetupIconFile=app.ico
Compression=lzma2
SolidCompression=yes
PrivilegesRequired=admin
WizardStyle=modern
[Languages]
Name: "chinesesimp"; MessagesFile: "ChineseSimplified.isl"
[Types]
Name: "full"; Description: "完整安装(推荐)"
Name: "server"; Description: "服务器安装"
Name: "client"; Description: "客户端安装"
Name: "custom"; Description: "自定义安装"; Flags: iscustom
[Components]
Name: "main"; Description: "主程序"; Types: full server client custom; Flags: fixed
Name: "database"; Description: "数据库服务"; Types: full server
Name: "web"; Description: "Web服务"; Types: full server
Name: "client"; Description: "客户端组件"; Types: full client custom
[Files]
Source: "..\Server*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: main
Source: "..\Database*"; DestDir: "{app}\Database"; Flags: ignoreversion; Components: database
Source: "..\Web*"; DestDir: "{app}\Web"; Flags: ignoreversion; Components: web
Source: "..\Client*"; DestDir: "{app}\Client"; Flags: ignoreversion; Components: client
[Run]
Filename: "{app}\Database\setup.exe"; Parameters: "/silent"; StatusMsg: "安装数据库..."; Components: database
Filename: "{app}\Web\install.exe"; Parameters: "/quiet"; StatusMsg: "配置Web服务..."; Components: web
Filename: "{app}\Client\Client.exe"; Description: "启动客户端程序"; Flags: nowait postinstall; Components: client
[Icons]
Name: "{group}\企业管理系统"; Filename: "{app}\Client\Client.exe"; Components: client
Name: "{group}\管理控制台"; Filename: "{app}\AdminConsole.exe"; Components: main
Name: "{group}\卸载企业管理系统"; Filename: "{uninstallexe}"

10.2 高级错误处理与日志记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[Code]
var
InstallLog: string;
procedure LogMessage(Msg: string);
begin
InstallLog := InstallLog + DateTimeToStr(Now) + ' - ' + Msg + #13#10;
SaveStringToFile(ExpandConstant('{tmp}\install.log'), InstallLog, True);
end;
function InitializeSetup(): Boolean;
begin
try
LogMessage('安装程序启动');
// 系统要求检查
if not IsAdminLoggedOn then begin
MsgBox('需要管理员权限运行安装程序。', mbError, MB_OK);
Result := False;
Exit;

第十一章:最佳实践与调试技巧

11.1 调试技巧

  1. 使用日志输出
1
MsgBox('调试信息: ' + SomeVariable, mbInformation, MB_OK);
  1. 启用详细日志
1
2
[Setup]
SetupLogging=yes
  1. 使用编译器指令
1
2
3
ifdef DEBUG
MsgBox('调试模式已启用', mbInformation, MB_OK);
endif

11.2 性能优化建议

  1. 文件压缩策略
1
Compression=lzma2/max
  1. 合理使用组件,避免不必要的文件复制

  2. 优化脚本逻辑,减少不必要的注册表操作

总结

通过本文的学习,您应该已经掌握了 Inno Setup 的核心概念和高级技巧。从基础的文件复制到复杂的数据库集成,从简单的安装界面到自定义的安装逻辑,Inno Setup 都能提供强大的支持。

关键要点回顾:

  1. 规划先行:在开始编写脚本前,明确安装需求和目标环境
  2. 模块化设计:合理使用组件和安装类型,提高灵活性
  3. 错误处理:完善的错误处理机制是专业安装包的标志
  4. 用户体验:清晰的提示和友好的界面同样重要
  5. 测试充分:在不同环境下全面测试安装包

Inno Setup 的学习曲线相对平缓,但功能深度很大。建议从简单的项目开始,逐步尝试更复杂的功能,最终能够制作出满足各种需求的专业级安装包。

致谢

笔者水平有限,内容参考:DeepSeek


本文基于实际项目经验编写,示例代码经过脱敏处理,可直接用于学习参考。建议在实际项目中根据具体需求进行调整和优化。