[Azure DevOps] 使用 Inno Setup 制作桌面软件安装包
1. 桌面应用程序的 CI/CD
桌面应用程序的 CI/CD 过程和网站有一些不同,毕竟桌面应用程序的“部署”只是将安装包分发到目标位置,连应用商店都不用上,根据公司的管理流程可以很复杂,也可以很简单。在简单的情况下,Azure Pipelines 中一个桌面应用(WPF)的 CI/CD 过程如下:
- 触发器启动 Pipeline
- 构建 WPF 应用程序
- 启动单元测试以确保构建质量
- 创建安装包
- 将安装包复制到目标位置
- 通知用户新安装包已经可以获取
在使用 Azure Pipelines 实现 CI 这篇文章中,我讲解了如何实现第 1、2、3、5 步。至于第 6 步,可以在 Project Settings 的 Notifications 页面中设置使用邮件通知团队成员,也可以参考 使用连接器接收Azure DevOps的通知 这篇文章通过 Teams 发送构建的结果。
现在我们还缺少第 4 步“创建安装包”,这篇文章将讲解如何在 Azure Pipelines 中使用 Inno Setup 创建安装包。
2. 使用 Inno Setup 创建安装包

假设我们已经根据 使用 Azure Pipelines 实现 CI 的做法发布了一个 WPF 应用程序,发布到 Artifacts 的文件将会如上图所示,可以以 Zip 的方式将所有输出文件下载到本地,基本相当于绿色版软件。但我们不能将这个 Zip 包直接发给客户,我们至少还要包括开始菜单和修改注册表什么的一大堆东西,所以需要将 Release 的文件打包到一个安装包中。我的公司通常使用 Inno Setup 制作安装包,在 Azure Pipelines 中使用 Inno Setup 也十分简单,于是这篇文章将使用 Inno Setup 作为制作安装包的例子。
首先我们需要一个 iss 脚本。在 install 目录下创建一个简单的名为 SetupScript.iss 的脚本文件,大部分保留了默认值(懒得修改公司名之类的了),它只是将 Release 目录的内容全部打包起来,内容如下:
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppName "My Program"
#define MyAppPublisher "My Company, Inc."
#define MyAppURL "https://www.example.com/"
#define MyAppExeName "wpf.exe"
#define VersionSourceAssemblyName MyAppExeName
#define BuildOutputFolder "..\wpf\bin\Release\"
#define MyAppFileVersion GetFileVersion(AddBackslash(BuildOutputFolder) + VersionSourceAssemblyName)
#define MyAppCustomerVersion GetStringFileInfo(AddBackslash(BuildOutputFolder) + VersionSourceAssemblyName, "ProductVersion")
[Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{0B50DAF7-728E-48C7-984F-5E6FDB924490}
AppName={#MyAppName}
AppVersion={#MyAppCustomerVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={autopf}\{#MyAppName}
DisableProgramGroupPage=yes
; Uncomment the following line to run in non administrative install mode (install for current user only.)
;PrivilegesRequired=lowest
OutputBaseFilename=mysetup {#MyAppCustomerVersion}
Compression=lzma
SolidCompression=yes
WizardStyle=modern
VersionInfoCompany={#MyAppPublisher}
VersionInfoVersion={#MyAppFileVersion}
VersionInfoProductName={#MyAppName}
VersionInfoProductTextVersion={#MyAppCustomerVersion}
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
Source: "{#BuildOutputFolder}{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#BuildOutputFolder}*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs;
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons]
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
用 Inno Setup 运行一下这个脚本文件确保它正确运行(如果成功的话会在 Installer\Output 目录下生成一个安装程序)。
3. 在 Azure Pipelines 上运行 Inno Setup
把 SetupScript.iss 推送到 Azure Repos 上,然后修改对应的 Pipeline。Pipeline 中需要添加两个任务:
- 一个负责使用 Chocolatey 下载并安装 Inno Setup 的任务
- 一个调用 Inno Setup 运行 SetupScript.iss 的任务
然后修改 CopyFiles 任务,将 Installer\output 目录中的安装包复制到 $(build.artifactstagingdirectory)。修改后的 YAML 文件如下(其中两个 PowerShell 任务即为新增的两个任务):
trigger:
- master
pool:
vmImage: 'windows-latest'
variables:
solution: '**/*.sln'
buildPlatform: 'Any CPU'
buildConfiguration: 'Release'
steps:
- task: NuGetToolInstaller@1
- task: PowerShell@2
displayName: 'Inno setup download'
inputs:
targetType: 'inline'
script: 'choco install innosetup'
- task: NuGetCommand@2
inputs:
restoreSolution: '$(solution)'
- task: VSBuild@1
inputs:
solution: '$(solution)'
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
- task: PowerShell@2
displayName: 'Execute Inno Setup script'
inputs:
targetType: 'inline'
script: 'iscc.exe Installer\\SetupScript.iss'
- task: CopyFiles@2
inputs:
SourceFolder: 'Installer\\output'
Contents: '*.exe'
TargetFolder: '$(build.artifactstagingdirectory)'
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'drop'
publishLocation: 'Container'
4. 最后
现在,一个桌面应用程序的 CI/CD 已经基本完成了。当然实际应用中 iss 脚本和 PowerShell 都可以更复杂以便完成更多任务,例如程序签名、检查并安装 .Net Framework 等,这些操作都超出了这篇文章的范畴,如有需要可以参考下面这些链接:
Inno Setup - a free installer for Windows programs
Chocolatey Software - The package manager for Windows
[Azure DevOps] 使用 Inno Setup 制作桌面软件安装包的更多相关文章
- 用Inno Setup制作WEB程序安装包
原文 用Inno Setup制作WEB程序安装包 最近做了一个WEB程序的安装包,我把制作的过程做个介绍,贴出源码给大家做个参考 看看inno 的脚本 [Setup] AppCopyright=tes ...
- Inno Setup制作应用程序安装包
我最近写了一个MFC应用程序,想发给其他的小伙伴玩一玩,直接发了个exe文件过去,结果发现小伙伴那边打不开.原来这个exe文件虽然是MFC静态编译的,但是还依赖了其他几个.dll文件,需要把这几个dl ...
- 用inno Setup制作web项目安装包
http://www.cnblogs.com/xionghui/archive/2012/03/22/2411207.html 用inno Setup制作安装包 新建一个文件夹exambody,放ap ...
- 用inno Setup做应用程序安装包的示例脚本(.iss文件)(
用innoSetup做应用程序安装包的示例脚本(.iss文件),具体要看innoSetup附带的文档,好象是pascal语言写的脚本. 示例1(应用程序.exe,客户端安装): ;{089D6802- ...
- 使用 InstallShield 制作 Delphi 软件安装包
软件版本: InstallShield 12 Delphi 5/7 SQL Server 2005 一.配置软件信息 二.软件安装的需求配置 三.安装架构 四.安装需要的文件 软件的安装路径.可执行文 ...
- 使用Inno Setup 制作软件安装包详细教程(与开发语言无关)
前言:关于如何制作一个软件安装包的教程,与编程语言无关.以下,请看详情~ 1.下载Inno Setup,下载地址:https://jrsoftware.org/isinfo.php 2.下载最新版本即 ...
- 快速创建软件安装包-ClickOnce
大家好,我是沙漠尽头的狼. .NET是免费,跨平台,开源,用于构建所有应用的开发人员平台. 今天介绍使用ClickOnce制作软件安装包,首先我们先了解什么是ClickOne. 1. 什么是Click ...
- 解决Inno Setup制作安装包无法创建桌面快捷方式的问题
转自:http://yedward.net/?id=104 昨天想把个java程序做成exe安装软件,然后就去下载了Inno Setup这个软件安装包制作软件,Inno Setup这个软件确实非常好用 ...
- Inno Step软件安装包制作教程
Inno setup制作软件安装包教程 1,Inno Setup介绍 Inno Setup 是一个免费的安装制作软件,小巧.简便.精美是其最大特点,支持pascal脚本,能快速制作出标准Windows ...
随机推荐
- js 实现 bind 的这五层,你在第几层?
最近在帮朋友复习 JS 相关的基础知识,遇到不会的问题,她就会来问我. 这不是很简单?三下五除二,分分钟解决. function bind(fn, obj, ...arr) { return fn.a ...
- Asp.NetCore Web开发之ADO.Net
Asp.NetCore可以说是.Net平台开发网站的一大利器,最近的一大段时间,就要跟大家分享,如何使用这一利器开发网站项目. 要学习网站开发,首先要学习如何使用ADO.Net进行数据库数据的增删改 ...
- Day015 异常处理机制
异常处理机制 抛出异常 捕获异常 异常处理的五个关键字 try:监控一个代码块,有异常就能通过catch捕获 catch(想要捕获的异常类型):捕获想要捕获的异常,catch代码块的代码只有在捕获到异 ...
- MFC对话框不能使用菜单更新宏ON_UPDATE_COMMAND_UI
菜单更新宏的原理 更新处理宏的工作原理是基于框架窗口类的.MFC中对话框菜单更新宏的原理是:当我们使用从CFrameWnd框架窗口类中派生的类创建窗口时,当我们单击菜单且菜单还未弹出前会产生WM_IN ...
- 反向解析 参数替换 reverse
- Linux命令nohup实现命令后台运行并输出到或记录到日志文件
Linux命令nohup实现命令后台运行并输出到或记录到日志文件 导读 我们在调试程序的时候,免不了要去抓一些 log ,然后进行分析.如果 log 量不是很大的话,那很简单,只需简单的复制粘贴就好. ...
- Linux_交换分区SWAP
一.交换分区SWAP 1️⃣:交换分区SWAP就是LINUX下的虚拟内存分区,它的作用是在物理内存使用完之后,将磁盘空间(也就是SWAP分区)虚拟成内存来使用. 2️⃣:交换分区一般指定虚拟内存的大小 ...
- Linux讲解之定时任务
https://www.php.cn/linux-369884.html Linux讲解之定时任务 原创2018-05-14 10:11:3101319 本文目录: 12.1 配置定时任务 1 ...
- 源码安装Apache(httpd)
[RHEL8] !!!测试环境我们首关闭防火墙和selinux [root@localhost ~]# systemctl stop firewalld [root@localhost ~]# sys ...
- TCP三次握手和四次挥手及对应端口状态
一.三次握手 1.第一次握手:Client 将标志位置为1,并向Server发送个seq=j,j为随机产生的数:等待Server回复,此时Client的端口状态为SYN_SENT. 2.第二次握手:S ...