当前位置: 首页 > news >正文

Inno Setup实战:打造智能安装包,解决依赖与开机启动难题

1. 从“能运行”到“开箱即用”:为什么你的程序需要一个真正的安装包

你花了好几个月,终于把那个用 Python 写的自动化工具,或者用 C++ 开发的小工具,又或者是基于 Electron 的桌面应用给搞定了。功能测试一切正常,你兴冲冲地把一个压缩包扔给同事或者客户。结果呢?对方反馈接踵而至:“哥们,你这程序打不开啊,提示缺少什么 DLL”、“我电脑上没装 Python,运行不了”、“怎么设置开机启动啊,每次都要手动点开好麻烦”。

我相信很多独立开发者或者小团队的技术负责人都遇到过这种窘境。你的程序在开发环境里跑得飞起,但到了用户手里就成了“薛定谔的软件”——能不能运行全看对方电脑的“缘分”。问题的核心在于,我们交付的往往只是一个“程序本体”,而非一个完整的“产品”。一个真正的产品,应该为用户屏蔽掉所有技术细节和依赖复杂性,做到下载、安装、使用三步走,甚至安装后就能自动在后台提供服务(开机启动)。

这就是 Inno Setup 这类安装包制作工具的价值所在。它不仅仅是一个“打包工具”,更是一个“用户体验设计工具”和“部署保障工具”。通过它,我们可以将程序本体、运行时环境(如 .NET Framework, VC++ Redistributable, Java JRE)、配置文件、注册表项、甚至后续的更新逻辑,打包成一个专业的、向导式的安装程序(.exe)。用户双击后,只需要点击“下一步”、“我同意”、“安装”,即可获得一个立即可用的软件,无需关心背后到底集成了哪些组件。

最近在技术社区和搜索引擎上,关于“依赖环境”和“开机启动”的讨论非常热络。比如“uniapp 运行报错 cli项目运行依赖本地的nodejs环境”,这本质就是运行时环境缺失的问题;而“笔记本开机后wifi启动慢”这类问题,也从侧面反映了用户对系统启动后服务自动就绪的强需求。对于我们自己开发的工具,如果是一个需要常驻的服务(比如监控客户端、同步工具、自动化脚本),开机自启就是刚需。手动让用户去创建快捷方式到启动文件夹,既不专业,也容易出错。

因此,今天我们就来深入聊聊,如何用 Inno Setup 这个经典、免费且强大的工具,打造一个不仅包含主程序,还能自动安装依赖环境、并实现开机启动的专业级安装包。我会结合我多次交付内部工具和中小型商业软件的经验,把其中的关键步骤、配置细节以及最容易踩的坑,毫无保留地分享给你。

2. Inno Setup 核心概念与项目结构解析

在动手写脚本之前,我们必须先理解 Inno Setup 是如何工作的,以及一个标准的安装包项目包含哪些部分。这能帮助我们在后面编写脚本时,清楚地知道每一行代码在干什么,而不是机械地复制粘贴。

Inno Setup 使用一种基于 Pascal 语道的脚本文件(.iss)来定义整个安装过程。这个脚本文件是纯文本的,你可以用任何文本编辑器编辑,但官方提供的 Inno Setup Compiler 界面(一个简易的 IDE)会更方便,它有语法高亮和编译按钮。一个典型的安装过程,可以分解为以下几个逻辑阶段,而我们的脚本就是对这些阶段进行定义:

  1. 安装向导界面:定义安装过程中出现的窗口、文字、选项框(比如是否创建桌面快捷方式,是否开机启动)。这部分对应脚本中的[Setup][Tasks]等节。
  2. 文件部署:指定将哪些源文件(你的程序文件、依赖的 DLL、配置文件等)复制到用户电脑的哪个目录下。这是核心,对应[Files]节。
  3. 系统配置:在用户电脑上创建注册表项、环境变量、开始菜单文件夹、关联文件类型等。对应[Registry],[Icons]等节。
  4. 执行外部操作:在安装前、中、后运行其他程序。这是我们用来安装依赖环境(如 VC++ 运行库)和设置开机启动的关键手段,对应[Run][UninstallRun]节。
  5. 卸载逻辑:定义如何干净地移除你的软件,包括删除哪些文件、清理哪些注册表项。一个专业的安装包必须包含完整的卸载功能,对应[UninstallDelete]和卸载时的[Run]节。

一个最基本的 .iss 脚本骨架如下:

; 脚本由 Inno Setup 脚本向导生成! ; 有关创建 Inno Setup 脚本文件的详细资料,请查阅帮助文档! #define MyAppName “我的程序” #define MyAppVersion “1.0” #define MyAppPublisher “我的公司” #define MyAppExeName “MyApp.exe” [Setup] ; 注意: AppId 的值是单独标识该应用程序的唯一标识。 ; 不要为其他安装程序使用相同的 AppId 值。 ; (生成新的 GUID,点击 工具|在 IDE 中生成 GUID。) AppId={{你的GUID} AppName={#MyAppName} AppVersion={#MyAppVersion} AppPublisher={#MyAppPublisher} DefaultDirName={autopf}\{#MyAppName} DefaultGroupName={#MyAppName} ; 移除下一行注释以在安装结束时禁止显示“Windows 保护了你的电脑”提示。 ;PrivilegesRequired=lowest OutputDir=. OutputBaseFilename=mysetup Compression=lzma SolidCompression=yes WizardStyle=modern [Languages] Name: “chinesesimplified”; MessagesFile: “compiler:Languages\ChineseSimplified.isl” [Tasks] Name: “desktopicon”; Description: “{cm:CreateDesktopIcon}”; GroupDescription: “{cm:AdditionalIcons}”; Flags: unchecked [Files] Source: “D:\MyProject\bin\Release\MyApp.exe”; DestDir: “{app}”; Flags: ignoreversion ; 注意: 不要在任何共享系统文件上使用“Flags: ignoreversion” [Icons] Name: “{group}\{#MyAppName}”; Filename: “{app}\{#MyAppName}” Name: “{commondesktop}\{#MyAppName}”; Filename: “{app}\{#MyAppName}”; Tasks: desktopicon [Run] Filename: “{app}\{#MyAppName}”; Description: “{cm:LaunchProgram,{#StringChange(MyAppName, ‘&’, ‘&&’)}}”; Flags: nowait postinstall skipifsilent

这个骨架脚本生成了一个非常基础的安装包。但我们的目标远不止于此。接下来,我们将在这个骨架上,重点强化两个能力:智能安装依赖环境配置开机启动

注意{app},{group},{pf}这些是 Inno Setup 的常量(Constants),它们会在安装时被动态替换为实际的路径,例如{app}代表用户选择的安装目录。使用常量能让你的脚本更通用,适应不同用户的系统设置。

3. 实战:为安装包集成运行时依赖环境

这是让我们的程序实现“开箱即用”最关键的一步。依赖环境缺失是软件部署中最常见的问题,没有之一。从热词中可以看到,jdk安装包.net framework 离线安装包vc_redist等都是高频搜索词,这正说明了用户和开发者对此的强烈需求。

我们的策略是:在安装主程序之前或之后,静默地安装这些运行时库。通常,我们将这些依赖包的安装放在主程序文件安装之后([Files]节),并在安装最后一步([Run]节)执行它们。为了用户体验,通常采用静默安装参数(如/quiet /norestart),不让用户看到额外的安装界面。

3.1 准备依赖安装包

首先,你需要获取依赖环境的离线安装包。以 Windows 平台最常见的几种为例:

  1. Microsoft Visual C++ Redistributable (VC++ Redist):这是绝大多数 C/C++ 程序的基石。你需要根据你的程序编译时使用的 Visual Studio 版本,准备对应的 x86 或 x64 安装包。例如,VS 2015-2022 的合并版本VC_redist.x64.exe。可以从微软官网下载。
  2. .NET Framework / .NET Desktop Runtime:如果你的程序基于 .NET Framework 4.x 或 .NET 5/6/7/8,需要准备对应的运行时安装包。对于 .NET Core 及更高版本,推荐使用“桌面运行时”(Desktop Runtime),因为它包含了运行桌面应用(WinForms, WPF)所需的一切。
  3. Java Runtime Environment (JRE):对于 Java 程序。你可以从 Adoptium 等网站下载.msi格式的离线安装包。
  4. 其他:如 DirectX End-User Runtimes、特定版本的 Node.js 等,根据你的程序需要准备。

关键点:务必使用离线安装包(通常文件较大,几十MB到上百MB),而不是在线安装器(一个几MB的引导程序)。因为你的用户安装时可能没有网络。

3.2 修改脚本:打包并静默安装依赖

假设我们的主程序MyApp.exe依赖 VC++ 2015-2022 Redist x64 和 .NET 6.0 Desktop Runtime x64。我们将修改[Files][Run]节。

首先,在[Files]节中,我们将这些依赖安装包也打包进我们的安装程序。通常,我们会将它们放在一个子目录(如deps\)中,以保持结构清晰。

[Files] ; 主程序 Source: “D:\MyProject\bin\Release\MyApp.exe”; DestDir: “{app}”; Flags: ignoreversion ; 你可以继续添加其他资源文件,如图片、配置文件等 ; Source: “D:\MyProject\config.ini”; DestDir: “{app}”; Flags: ignoreversion ; 依赖包 - 将它们复制到安装目录下的一个子文件夹,避免污染根目录 Source: “D:\Dependencies\VC_redist.x64.exe”; DestDir: “{app}\deps”; Flags: ignoreversion deleteafterinstall Source: “D:\Dependencies\windowsdesktop-runtime-6.0.xx-win-x64.exe”; DestDir: “{app}\deps”; Flags: ignoreversion deleteafterinstall

注意Flags中的deleteafterinstall。这个标志非常有用,它告诉 Inno Setup 在安装过程结束后删除这个文件。这样,依赖包只在安装时被临时解压到用户电脑上,运行完后就被清理,不会占用用户额外的磁盘空间。

接下来,在[Run]节中,我们添加执行这些依赖安装的命令。这里有一个非常重要的技巧:先检查系统是否已安装该依赖,避免重复安装。重复安装虽然通常无害,但会浪费用户时间,并可能弹出不必要的重启提示。

我们可以利用 Inno Setup 的Check参数和RegKeyExists,GetEnv等函数来实现条件执行。

[Run] ; 静默安装 VC++ Redist (如果尚未安装) ; 通过检查注册表来判断是否已安装 Filename: “{app}\deps\VC_redist.x64.exe”; Parameters: “/install /quiet /norestart”; StatusMsg: “正在安装 Microsoft Visual C++ 运行库…”; Check: not VCRedistInstalled ; 静默安装 .NET 6 Desktop Runtime (如果尚未安装) ; 通过检查注册表和系统路径来判断 Filename: “{app}\deps\windowsdesktop-runtime-6.0.xx-win-x64.exe”; Parameters: “/install /quiet /norestart”; StatusMsg: “正在安装 .NET 6 桌面运行时…”; Check: not DotNetRuntimeInstalled ; 最后,可选地运行主程序 Filename: “{app}\MyApp.exe”; Description: “运行 {#MyAppName}”; Flags: nowait postinstall skipifsilent

3.3 实现自定义检查函数

上面的Check: not VCRedistInstalledCheck: not DotNetRuntimeInstalled是自定义函数调用。我们需要在脚本的[Code]节(这是一个用于编写 Pascal 代码的节)中实现这些函数。

[Code] // 函数:检查 VC++ 2015-2022 Redist (x64) 是否已安装 function VCRedistInstalled: Boolean; var Version: String; begin // 通过注册表检查。不同版本的VC++ Redist有不同的GUID。 // 对于 VS 2015-2022 的合并包,可以检查这个键 if RegQueryStringValue(HKLM, ‘SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64’, ‘Version’, Version) then begin // 如果找到了版本号,说明已安装 Result := True; end else begin Result := False; end; end; // 函数:检查 .NET 6 Desktop Runtime 是否已安装 function DotNetRuntimeInstalled: Boolean; var InstallRoot: String; begin // .NET Core/5+ 运行时信息通常在这个注册表路径下 if RegQueryStringValue(HKLM, ‘SOFTWARE\dotnet\Setup\InstalledVersions\x64\sharedhost\’, ‘Version’, InstallRoot) then begin // 这里我们简化处理:只要找到了这个键,就认为有某个版本的运行时。 // 更严谨的做法是读取版本号并与所需版本比较。 Result := True; end else begin Result := False; end; end;

通过这样的设计,我们的安装包就具备了“智能”安装依赖的能力。它会先探测用户的系统环境,只安装缺失的组件,从而让安装过程既完整又高效。

4. 实现开机启动:从用户选项到系统服务

开机启动是很多工具类软件的必备功能。实现方式主要有三种,各有优劣,适用于不同场景:

  1. 启动文件夹快捷方式:最简单,将程序的快捷方式放入用户的启动文件夹。适合普通桌面应用,需要用户登录后才启动。
  2. 注册表自启动项:将程序路径写入HKCU\Software\Microsoft\Windows\CurrentVersion\Run(当前用户)或HKLM\...\Run(所有用户)。比启动文件夹更隐蔽,同样是用户登录后启动。
  3. Windows 服务:最高级,程序以系统服务形式运行,无需用户登录即可启动,拥有更高的权限和稳定性。适合后台守护进程。

对于大多数桌面工具,我们通常提供选项让用户选择是否开机启动,采用第1或第2种方式。这里我们以“通过注册表项 + 用户可选任务”为例,因为它更灵活,且能通过安装脚本和卸载脚本统一管理。

4.1 在安装向导中添加用户选项

首先,我们在[Tasks]节中添加一个任务(Task),让用户在安装时可以选择。

[Tasks] Name: “desktopicon”; Description: “创建桌面快捷方式”; GroupDescription: “附加图标:”; Flags: unchecked Name: “autostart”; Description: “开机时自动启动 {#MyAppName}”; GroupDescription: “其他任务:”; Flags: unchecked

这样,安装界面上就会多出一个复选框:“开机时自动启动 我的程序”。

4.2 根据用户选择写入注册表

然后,我们在[Registry]节中,根据用户是否勾选了autostart任务,来决定是否创建注册表项。

[Registry] ; 如果用户勾选了“开机启动”任务,则在当前用户的Run键下创建自启动项 Root: HKCU; Subkey: “SOFTWARE\Microsoft\Windows\CurrentVersion\Run”; ValueType: string; ValueName: “{#MyAppName}”; ValueData: “{app}\MyApp.exe”; Flags: uninsdeletevalue; Tasks: autostart

解释一下关键参数:

  • Root: HKCU:写入当前用户(HKEY_CURRENT_USER)的注册表,这样不需要管理员权限。如果希望为所有用户设置,需要管理员权限并改用HKLM
  • Subkey:自启动项的标准路径。
  • ValueName:项的名称,这里我们直接用程序名。
  • ValueData:项的值,即要运行的程序完整路径。{app}会被替换为实际的安装目录。
  • Flags: uninsdeletevalue:非常重要!这个标志表示在卸载时,会自动删除这个注册表值。这确保了我们的软件能够被干净地移除,不会留下垃圾启动项。
  • Tasks: autostart:这个条件语句确保了只有用户勾选了autostart任务时,这段注册表操作才会执行。

4.3 进阶:以管理员权限运行并注册系统服务

如果你的程序是一个需要高权限、或者需要在用户登录前就运行的后台服务,那么创建 Windows 服务是更专业的选择。这通常需要你的程序本身支持以服务模式运行(例如,在 .NET 中可以使用TopshelfBackgroundService;在 C++ 中可以调用服务控制管理器 API)。

在 Inno Setup 中,我们可以通过[Run]节,在安装后以管理员权限执行一个命令来注册服务。假设你的程序MyService.exe支持通过install参数安装服务。

[Run] ; … 其他运行命令,如安装依赖 … ; 注册为 Windows 服务(需要管理员权限) Filename: “{app}\MyService.exe”; Parameters: “install”; StatusMsg: “正在注册系统服务…”; Flags: runhidden waituntilterminated; Check: IsAdminInstallMode ; 启动服务 Filename: “net”; Parameters: “start MyServiceName”; StatusMsg: “正在启动服务…”; Flags: runhidden waituntilterminated; Check: IsAdminInstallMode

同时,在[UninstallRun]节中,我们需要在卸载前停止并删除服务。

[UninstallRun] ; 卸载前停止并删除服务 Filename: “net”; Parameters: “stop MyServiceName”; Flags: runhidden waituntilterminated; Check: IsAdminInstallMode Filename: “{app}\MyService.exe”; Parameters: “uninstall”; Flags: runhidden waituntilterminated; Check: IsAdminInstallMode

重要提示:注册和操作 Windows 服务需要管理员权限。在[Setup]节中,你需要设置PrivilegesRequired=adminPrivilegesRequiredOverridesAllowed=dialog,这样安装程序启动时就会请求管理员权限。IsAdminInstallMode函数在安装程序以管理员权限运行时返回True

5. 避坑指南与高级技巧:打造更稳健的安装体验

掌握了核心功能后,我们还需要关注一些细节和边界情况,这些往往是决定你的安装包是否专业、是否 robust 的关键。

5.1 依赖安装的“静默”与“重启”难题

坑点1:静默安装参数不统一。不同厂商的安装包静默参数可能不同。VC++ Redist 通常用/install /quiet /norestart,.NET 安装器用/install /quiet /norestart,但有些老版本的 .NET Framework 可能用/q。Java JRE 的.msi包则用/quiet务必查阅你所使用的特定依赖包的官方文档或通过安装包.exe /?查看命令行帮助

坑点2:安装后需要重启。某些系统级组件(如某些旧版本的 .NET Framework)安装后可能要求重启。虽然我们加了/norestart参数,但系统可能仍会标记“挂起的重启”。一个处理方法是,在安装完所有组件后,通过[Code]节检查是否需要重启,并提示用户。

[Code] procedure CurStepChanged(CurStep: TSetupStep); begin if CurStep = ssPostInstall then begin // 检查是否需要重启 if IsPendingReboot then begin MsgBox(‘安装完成。某些更改需要重启计算机才能生效。建议您重启电脑。’, mbInformation, MB_OK); end; end; end; function IsPendingReboot: Boolean; begin // 检查常见的“挂起重启”注册表标志 Result := (RegKeyExists(HKLM, ‘SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations’)) or (RegValueExists(HKLM, ‘SYSTEM\CurrentControlSet\Control\Session Manager’, ‘SetupExecute’)) or (RegValueExists(HKLM, ‘SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing’, ‘RebootPending’)); end;

5.2 开机启动的路径与参数问题

坑点3:路径中的空格。如果你的安装路径或程序名包含空格(例如C:\Program Files\My Tool\MyApp.exe),直接将其写入注册表的Run项可能会导致启动失败。最佳实践是使用双引号包裹整个路径。Inno Setup 的常量{app}在解析时不会自动加引号,所以我们需要手动处理。

[Registry] Root: HKCU; Subkey: “SOFTWARE\Microsoft\Windows\CurrentVersion\Run”; ValueType: string; ValueName: “{#MyAppName}”; ValueData: “””{app}\MyApp.exe”””; Flags: uninsdeletevalue; Tasks: autostart

注意ValueData中的”””{app}\MyApp.exe”””。外层的两个双引号是 Pascal 字符串的转义,实际写入注册表的值会是”C:\Program Files\My Tool\MyApp.exe”

坑点4:带参数启动。如果你的程序需要带参数启动(例如MyApp.exe -minimized),只需在ValueData中加上即可:”””{app}\MyApp.exe”” -minimized”

5.3 版本管理与升级安装

坑点5:覆盖安装与旧版本清理。当用户安装新版本时,默认行为是覆盖安装到同一目录。这通常没问题,但有时旧版本可能遗留了一些不再需要的文件。你可以在[InstallDelete]节中指定在安装前删除某些旧文件或目录。更常见的需求是,在安装新版本前,自动结束旧版本正在运行的进程。

[Code] function InitializeSetup(): Boolean; begin Result := True; // 尝试终止正在运行的旧版本进程 if not ShellExec(‘’, ‘taskkill.exe’, ‘/f /im MyApp.exe’, ‘’, SW_HIDE, ewWaitUntilTerminated, ExitCode) then begin // taskkill 可能失败(例如进程不存在),这通常是正常的,可以记录日志但不要阻止安装 Log(‘尝试结束进程 MyApp.exe 时发生错误或进程不存在。’); end; end;

5.4 自定义界面与安装前环境检测

为了让安装包更友好,我们可以进行前置环境检测。例如,如果你的程序必须运行在 Windows 10 或更高版本,或者必须要有管理员权限,可以在脚本一开始就检查。

[Code] function InitializeSetup(): Boolean; var Version: TWindowsVersion; begin Result := True; GetWindowsVersionEx(Version); // 检查 Windows 版本 if Version.Major < 10 then begin MsgBox(‘本软件需要 Windows 10 或更高版本的操作系统。’, mbError, MB_OK); Result := False; Exit; end; // 检查是否以管理员身份运行(对于需要安装服务的场景) if not IsAdminLoggedOn then begin if MsgBox(‘本安装程序需要管理员权限。是否继续?’, mbConfirmation, MB_YESNO) = IDYES then begin // 实际上,Inno Setup 通过 PrivilegesRequired=admin 会自己提权 // 这里只是示例,更复杂的逻辑可以放在这里 end else begin Result := False; end; end; end;

6. 完整脚本示例与编译测试

将以上所有部分整合,一个功能相对完整的 .iss 脚本示例如下。请根据你的实际项目路径和需求进行调整。

; 定义常量,便于维护 #define MyAppName “我的超级工具” #define MyAppVersion “1.0.0” #define MyAppPublisher “我的工作室” #define MyAppExeName “SuperTool.exe” #define MyAppId “{{你的GUID}” ; 使用工具生成唯一GUID [Setup] AppId={#MyAppId} AppName={#MyAppName} AppVersion={#MyAppVersion} AppPublisher={#MyAppPublisher} DefaultDirName={autopf}\{#MyAppName} DefaultGroupName={#MyAppName} ; 如果需要操作注册表自启动(HKCU不需要admin)或安装服务,则可能需要admin权限 ; PrivilegesRequired=lowest ; PrivilegesRequiredOverridesAllowed=dialog OutputDir=.\Output OutputBaseFilename={#MyAppName}_Setup_v{#MyAppVersion} Compression=lzma2/ultra SolidCompression=yes WizardStyle=modern ; 设置安装程序图标 SetupIconFile=.\assets\setup.ico [Languages] Name: “chinesesimplified”; MessagesFile: “compiler:Languages\ChineseSimplified.isl” [Tasks] Name: “desktopicon”; Description: “创建桌面快捷方式”; GroupDescription: “附加图标:”; Flags: unchecked Name: “autostart”; Description: “开机时自动启动 {#MyAppName}”; GroupDescription: “其他任务:”; Flags: unchecked [Files] ; 主程序文件 Source: “.\build\Release\{#MyAppExeName}”; DestDir: “{app}”; Flags: ignoreversion ; 其他资源文件 Source: “.\build\Release\config.json”; DestDir: “{app}”; Flags: ignoreversion Source: “.\build\Release\*.dll”; DestDir: “{app}”; Flags: ignoreversion recursesubdirs createallsubdirs ; 依赖包(安装后删除) Source: “.\deps\VC_redist.x64.exe”; DestDir: “{app}\deps”; Flags: ignoreversion deleteafterinstall Source: “.\deps\windowsdesktop-runtime-6.0.xx-win-x64.exe”; DestDir: “{app}\deps”; Flags: ignoreversion deleteafterinstall [Icons] Name: “{group}\{#MyAppName}”; Filename: “{app}\{#MyAppExeName}” Name: “{commondesktop}\{#MyAppName}”; Filename: “{app}\{#MyAppExeName}”; Tasks: desktopicon [Registry] ; 开机自启动(用户可选) Root: HKCU; Subkey: “SOFTWARE\Microsoft\Windows\CurrentVersion\Run”; ValueType: string; ValueName: “{#MyAppName}”; ValueData: “””{app}\{#MyAppExeName}”””; Flags: uninsdeletevalue; Tasks: autostart [Run] ; 安装依赖(条件执行) Filename: “{app}\deps\VC_redist.x64.exe”; Parameters: “/install /quiet /norestart”; StatusMsg: “正在安装 Microsoft Visual C++ 运行库…”; Check: not VCRedistInstalled Filename: “{app}\deps\windowsdesktop-runtime-6.0.xx-win-x64.exe”; Parameters: “/install /quiet /norestart”; StatusMsg: “正在安装 .NET 6 桌面运行时…”; Check: not DotNetRuntimeInstalled ; 安装完成后运行主程序 Filename: “{app}\{#MyAppExeName}”; Description: “启动 {#MyAppName}”; Flags: nowait postinstall skipifsilent [Code] function VCRedistInstalled: Boolean; var Version: String; begin Result := RegQueryStringValue(HKLM, ‘SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64’, ‘Version’, Version); // 更健壮的检查可以解析Version并与所需版本比较 if not Result then begin // 也可以检查其他可能的注册表路径 Result := RegKeyExists(HKLM, ‘SOFTWARE\WOW6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x64’); end; end; function DotNetRuntimeInstalled: Boolean; begin // 检查 .NET 6+ 运行时是否存在 Result := RegKeyExists(HKLM, ‘SOFTWARE\dotnet\Setup\InstalledVersions\x64\sharedhost’); if not Result then begin // 对于 x86 系统或安装在32位路径下的情况 Result := RegKeyExists(HKLM, ‘SOFTWARE\dotnet\Setup\InstalledVersions\x86\sharedhost’); end; end; procedure CurStepChanged(CurStep: TSetupStep); begin if CurStep = ssPostInstall then begin // 可选:安装完成后提示信息 // MsgBox(‘安装成功!’, mbInformation, MB_OK); end; end;

编译与测试

  1. 将上述脚本保存为MyAppSetup.iss
  2. 准备好你的程序文件(放在.\build\Release\)、依赖包(放在.\deps\)和图标。
  3. 打开 Inno Setup Compiler,加载这个 .iss 文件。
  4. 点击工具栏上的“编译”按钮(或按 F9)。
  5. 编译成功后,在.\Output目录下会生成我的超级工具_Setup_v1.0.0.exe
  6. 至关重要的步骤:在一个干净的测试环境(如虚拟机)中运行这个安装包,从头到尾走一遍流程,测试所有功能:安装路径选择、依赖是否静默安装、开机启动选项是否生效、程序能否正常启动、卸载是否干净。这是保证交付质量的最后一道,也是最重要的一道关卡。

通过以上步骤,你就能打造出一个真正专业、用户友好的 Windows 程序安装包。它不仅能交付你的软件,更能交付一份完整的、无忧的体验。记住,安装包是你的软件给用户的第一印象,一个可靠、智能的安装过程,本身就是产品价值的一部分。

http://www.jsqmd.com/news/1350461/

相关文章:

  • palera1n越狱工具:如何让旧款iPhone重获新生?终极指南
  • SQL Server内存数据库优化与高并发实战
  • 抖音无水印下载器终极指南:3步轻松保存高清视频
  • 300元AI编程实验:Claude Fable 5开发Electron桌面应用全记录
  • AI Agent与低代码平台融合:架构设计与工程实践
  • SQL注入攻击原理、防御与实战案例分析
  • 2026年辣椒去柄机源头厂家有哪些,选卡赫农业装备(诸城)有限公司 - 热点品牌推荐
  • 从GPT到GLM-5.1:Agent框架大语言模型迁移实战与深度对比
  • 解决Windows下npm安装EBUSY错误的全面指南
  • 数字IC/FPGA工程师简历撰写指南:从万能模板到STAR法则实战
  • 权限认证与项目集成:RBAC模型与微服务实践
  • 深度学习入门实战:从环境配置到项目部署的完整指南
  • 合成数据驱动工业视觉:YOLOv11在风电叶片关键点检测的实践
  • 腾讯AI Skills社区体验:高速下载与1.3万技能的高效管理实践
  • C++可变参数模板详解:从原理到实战实现类型安全泛型编程
  • 2026年8月大连紧固件晋亿代理经销商/大连新能源汽车紧固件配套商哪家正规_大连百年融创科技有限公司 - 行业平台推荐
  • 企业级LLM多Agent系统架构实战:从ERP集成到智能流程自动化
  • SqlSugar在C#中的高效数据库操作实践
  • AI眼镜如何以“静默增强”技术破解日本垂直行业效率难题
  • LangGraph实战:构建有状态AI工作流的核心概念与工程实践
  • 龙蜥OS运维实战:静态IP配置与Nginx服务部署全解析
  • 构建有状态LLM系统评测框架:从原理到工程实践
  • DN50/DN100伸缩套管与预埋钢套管供货商甄选参考:杭州地区专业厂家综合评估 - 优质品牌商家
  • 基于Django与协同过滤的校园音乐推荐系统实践
  • 连续投影算法(SPA)原理与实战:光谱特征选择降维指南
  • OpenClaw:AI Agent时代的软件架构变革
  • 如何让你的Windows 11/10系统重获新生:Win11Debloat终极优化指南
  • 适配器实现闭环控制
  • 3分钟解锁PC游戏完整震动体验:X1nput终极配置指南
  • Conda环境管理工具核心功能与实战技巧