Inno Setup 打包脚本总结

  • 1.1. 脚本段
    • 1.1.1. #define宏定义常量
    • 1.1.2. [Setup]
    • 1.1.3. AppId
      • 1.1.3.1. ShowLanguageDialog
      • 1.1.3.2. ArchitecturesAllowed
      • 1.1.3.3. LicenseFile
    • 1.1.4. [Languages]
    • 1.1.5. [Files]
    • 1.1.6. [Tasks]
    • 1.1.7. [Icons]
    • 1.1.8. [Registry]
    • 1.1.9. [Run]
    • 1.1.10. [UninstallRun]
    • 1.1.11. [UninstallDelete]
    • 1.1.12. [code]
  • 1.2. 安装或卸载前检查程序是否正在运行
    • 1.2.1. 查找程序进程名关闭进程
    • 1.2.2. 查找窗口名关闭进程
    • 1.2.3. 封装dll检测和关闭进程
    • 1.2.4. Inno Setup 脚本创建互斥量
  • 1.3. 安装前检测程序已安装过
  • 1.4. 卸载前确认是否备份数据
    • 1.4.1. 卸载前检查
    • 1.4.2. 确认卸载后备份数据再卸载
    • 1.4.3. 卸载时不备份数据进行身份验证
    • 1.4.4. 备份数据
    • 1.4.5. 压缩文件夹
  • 1.5. 添加 readme 文件
  • 1.6. 参考
  • 1.7 软件安装包

Inno Setup 使用版本为 6.1.2
系统为 win7 64位

1.1. 脚本段

1.1.1. #define宏定义常量

#define MyAppDirName "Demo"
#define MyAppVersion "1.0"
#define MyAppVerData "20210204"
#define MyAppExeName "Demo.exe"
#define MyAppName "Demo"
...

定义后在后面[Code]代码段需要使用时,用ExpandConstant('{#MyAppVersion}')将其转换为字符串。

除了自定义的常量,还有一些预定义的常量,如常用的{app},表示用户在安装时选择的安装目录,该常量不能再安装过程中使用,可用于卸载过程。
ExpandConstant('{app}')得到安装目录路径的字符串值。

1.1.2. [Setup]

AppName={#MyAppName}
AppVersion={#MyAppVersion}
WizardStyle=modern
...

这个段包含用于安装程序和卸载程序的全局设置。

1.1.3. AppId

AppId={{1FE691F8-AD24-43CC-B5F7-78481C10D59A}}

这里右边为常量,根据帮助文档说明:

字符“{”视作为常量开始。如果你想将它作为实际字符使用,你必须使用两个连续的“{”字符。(对于“}”则不需要。)

因此AppId实际值为{1FE691F8-AD24-43CC-B5F7-78481C10D59A}}

点击 Tools 可选择Generate GUID生成GUID作为AppIdAppId 再在后面添加一个_is1,可以确定实际卸载注册表键名。

以本脚本为例,安装的软件在卸载注册表中位置为:

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows
\CurrentVersion\Uninstall\{1FE691F8-AD24-43CC-B5F7-78481C10D59A}}_is1]

卸载注册表中可看见软件名字,版本信息,安装文件夹路径,卸载程序位置(如"D:\unins,exe")等信息。
如果卸载注册表键名重复,Inno Setup 会删除之前的键然后新建,但两个重复的程序都会有问题。因此AppId要唯一,区别于其他程序。有些软件以软件名为键名,如360安全卫士

1.1.3.1. ShowLanguageDialog

当设置为 yes 并且有多个[Languages] 段条目时,将显示一个选择语言对话框,让用户有机会选择安装程序的语言。(默认)

当设置为 no 时,将从不显示对话框。

当设置为 auto 时,对话框只在安装程序不能找到匹配的语言标识时显示。

1.1.3.2. ArchitecturesAllowed

有效值: 一个或多个如下内容,以空格分隔:

x86
x64
ia64

默认值: (blank)

确切说明哪种处理器架构允许安装程序在上面运行。如果这指令没被指定或者是空白的,安装将被允许在能执行它的32位代码的全部处理器架构上运行(including ones it doesn’t recognize)。

如果你安装任何32位设备驱动,你应该将此指令设定为 x86,由于32位设备驱动程序无法运行在64位 Windows。

如果你的应用程序的二进制构建成为 X64 或是 Itanium 架构,you should set this directive to either x64 或 ia64 respectively。

Inno Setup 是32位,如果没特别设置,即使系统是64位,打包的软件是32位。

1.1.3.3. LicenseFile

LicenseFile=license.txt

指定许可协议文件名 (可选),用 .txt 或 .rtf (富文本) 格式,在用户选择程序目标目录前显示。在运行安装程序编译器时,这个文件必须位于你的安装程序的来源目录,除非你指定了完整的路径,或用“compiler:”作为前缀,在这种情况下将在编译器目录下查找文件。

如果设置 LicenseFile 则显示。用户只能在选定“我同意该协议”的情况下才能继续到一页。

1.1.4. [Languages]

Name: "Chinese"; MessagesFile: "compiler:Languages\ChineseSimplified.isl"

这里只用了简体中文一种语言,语言文件位于 Inno Setup 软件的安装文件Languages文件夹中,官方没有简体中文语言,需下载 ChineseSimplified.isl语言文件后放在该文件夹中。

语言文件中路径以compiler:为前缀,则会在编译器目录下查找该文件。

因该语言文件非官方,可能有翻译错误地方,如需修改可对照默认的语言文件(与编译器目录相同,名字为Default.isl)进行翻译。

1.1.5. [Files]

Source: "{#OutPut}\backup.bat"; DestDir: "{Demo}"; Flags: replacesameversion
Source: "{#OutPut}\*.bat"; DestDir: "{app}"; Flags: replacesameversion

这是定义安装程序安装文件到用户系统中的可选文件段。

Source:文件来源名字,这里指定文件完整路径。
DestDir:文件安装到用户系统中的目录。基本上都是用一个目录常量开头。如果指定的路径在用户系统中不存在,它会自动创建,并在卸载后如果是空的,卸载程序会自动删除。

1.1.6. [Tasks]

Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}";
Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}";
;Name: "startupicon"; Description: "开机启动"; GroupDescription: "{cm:AdditionalIcons}";

这个段是只选的。它定义安装程序在执行安装期间所有由用户定制的任务。这些任务以选项框和单选项形式在附加任务向导页中出现。

{cm:CreateDesktopIcon}是自定义消息常量,常用的一些在.isl的语言文件中已经描述,如有 其它需要自定义的可在[CustomMessages]段定义。

[CustomMessages]
CreateDesktopIcon=创建桌面快捷方式(&D)[Tasks]
Name: desktopicon; Description: "{cm:CreateDesktopIcon}"

GroupDescription为任务组的组描述,可以包含常量。用相同组描述的任务将被连续组合到文字标签下。文字标签显示组描述。

还可添加Flags,参数说明见帮助文档。

这里创建两个任务:创建桌面快捷方式和创建快速运行栏快捷方式,但光任务本身是不会做任何事情的: 它需要“链接”到其它安装条目。

[Icons]
Name: "{commondesktop}\{#MyDemoName}"; Filename: "{Demo}\{#MyDemoExeName}"; Tasks: desktopicon
Name: "{userDemodata}\Microsoft\Internet Explorer\Quick Launch\{#MyDemoName}"; Filename: "{Demo}\{#MyDemoExeName}"; Tasks: quicklaunchicon

1.1.7. [Icons]

[Icons]
Name: "{group}\{#MyDemoName}"; Filename: "{Demo}\{#MyDemoExeName}"
Name: "{group}\{cm:UninstallProgram,{#MyDemoName}}"; Filename: "{uninstallexe}"
Name: "{commondesktop}\{#MyDemoName}"; Filename: "{Demo}\{#MyDemoExeName}"; Tasks: desktopicon
Name: "{userDemodata}\Microsoft\Internet Explorer\Quick Launch\{#MyDemoName}"; Filename: "{Demo}\{#MyDemoExeName}"; Tasks: quicklaunchicon

这个可选段定义所有创建在开始菜单和/或其它位置 (比如桌面) 的快捷方式。

Name:要创建的快捷方式的名字和位置。
Filename:快捷方式的命令行文件名,通常用一个目录常量开头,可执行程序文件位置。
Tasks:与[Tasks]段中创建的任务关联,选择该任务,则处理该条目。

外壳文件夹常量:
{group}:开始菜单文件夹路径。这个文件夹总是创建在所有用户配置文件下,除非安装是在Non Administrative Install Mode,这种情况下它将创建在当前用户配置文件下。
如:C:\ProgramData\Microsoft\Windows\Start Menu\Programs

{commondesktop}:桌面文件夹路径,如C:\Users\Public\Desktop

{userDemodata}:Demolication Data文件夹路径,

1.1.8. [Registry]

Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Run"; ValueType: string; valueName: "Demo"; ValueData: "{Demo}\{#MyDemoExeName}"; Flags: uninsdeletevalue

这个可选段用来定义一些你想用安装程序在用户系统中创建、修改或删除的注册表键/值。
按默认,用安装程序创建的注册表键和值在卸载时不删除。如果你想让卸载程序删除键或值,你必须包含 uninsdelete* 标记中的一个。

Root:根键,为下列中一个:

HKCR  (HKEY_CLASSES_ROOT)
HKCU  (HKEY_CURRENT_USER) //当前用户
HKLM  (HKEY_LOCAL_MACHINE) //当前机器,所有用户登录都可执行
HKU  (HKEY_USERS)
HKCC  (HKEY_CURRENT_CONFIG)

Subkey:子键名。

ValueType:值的数据类型,为下列一个:

none //默认设置,安装程序将创建一个没有键值的键,在这种情况下,ValueName 和 ValueData 参数将被忽略。
string //安装程序将创建一个字符串 (REG_SZ) 值
expandsz
multisz
dword
qword
binary

valueName:要创建的值名,可以包含常量。如果是空白的,将写入到“默认”值。如果 ValueType 参数设置为 none,这个参数被忽略。

ValueData:值的数据。如果 ValueType 参数是 string,expandsz 或 multisz,这是这一个可以包含常量的字符串。如果数据类型是 none,将被忽略。

Flags:这个参数是额外选项设置。多个选项可以使用空格隔开。支持参数见帮助文档。
uninsdeletevalue:当程序卸载时删除该值。

示例中要在注册表中创建开机自启项。注册表添加启动项一般在Run键(如果只执行一次用RunOnce),常用的两个位置在HKCUHKLM两个根键下。
这里创建的键的位置为HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run,在本机(win7 64位)或 win10 64 系统的注册表中查找时,发现实际的位置在HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run

因为系统是64位,而打包的软件为32位,因此创建的键位置重定向在Wow6432Node下。见MSDN官网说明。

给程序添加开机自启除了加到注册表中,还可添加到启动文件夹:

[Tasks]
Name: "startupicon"; Description: "开机启动"; GroupDescription: "{cm:AdditionalIcons}";[Icons]
Name: "{commonstartup}\{#MyDemoName}"; Filename: "{Demo}\{#MyDemoExeName}"; Tasks: startupicon

{userstartup} & {commonstartup} * :开始菜单启动文件夹路径。
common 常量引用到所有用户配置文件。
user常量引用到当前登录的用户配置文件进行安装。

启动优先级: 注册表启动 > 启动文件夹

1.1.9. [Run]

该段是可选的, 可以放一些程序在程序成功安装后执行, 注意该执行过程是在应用程序弹出最后的安装完成的界面前

Filename: "{app}\MyProg.exe"; Parameters:"传递参数"; Description: "应用程序的描述"; Flags: runhidden runascurrentuser

上述例子中添加 runhidden 标志可以执行该程序而不显示窗口, 无需用户交互时使用
可以设置 postinstall 如果希望在界面显示一个是否执行该程序勾选框, 如果用户取消勾选则不会执行

1.1.10. [UninstallRun]

和 [Run] 一样是可选的, 语法也同 [Run] 相同, 用于执行 uninstallation 的第一步时执行, 即卸载时执行

1.1.11. [UninstallDelete]

Type: filesandordirs; Name: "{Demo}\UserData" //目录,删除所有文件和子目录
Type: files; Name: "{Demo}\temp.bat" //文件

这个可选段定义你想让卸载程序删除除用 [Files][Dirs]条目安装/创建外的其它文件或目录,或由你应用程序创建的一些公共使用的 .INI 文件。
卸载程序在卸载时最后一步处理这些条目。

Type

files:
该 Name 参数指定一个详细的文件名,或带通配符的文件名。filesandordirs :
除同时还匹配目录名外,功能与 files 相同,并删除任何名字匹配的目录以及包含它们中的所有文件和子目录。dirifempty:
当使用这个参数时,Name 参数必须是目录名,但它不能包含通配符。该目录只在不包含任何文件或子目录的情况下才被删除。

1.1.12. [code]

可选的指定 Pascal 脚本的段。

1.2. 安装或卸载前检查程序是否正在运行

1.2.1. 查找程序进程名关闭进程

varBCanFindTask: Boolean; //全局变量 查找进程过程出错则为Falsefunction FindTask(): Boolean;
varStrTempFilePath, StrCmdFindTask: String;StrTempFileContent: AnsiString;ResultCode: Integer;
begin//getCurrentDir() 返回返回包含当前目录名的字串。这里返回的路径为 OutputDir 的路径StrTempFilePath := getCurrentDir() + '\findTaskTempFile.txt'; //创建临时文件Log('StrTempFileDir = ' +  StrTempFilePath); //调式时查看变量值StrCmdFindTask := Format('/c tasklist|find /c /i "%s" > "%s"', [ExpandConstant('{#MyDemoExeName}'), StrTempFilePath]);BCanFindTask := ShellExec('open', ExpandConstant('{cmd}'), StrCmdFindTask, '', SW_HIDE, ewWaitUntilTerminated, ResultCode);if BCanFindTask then beginBCanFindTask := LoadStringFromFile(StrTempFilePath, StrTempFileContent); //将文件中内容输出到字符串StrTempFileContentLog('StrTempFileContent = ' +  StrTempFileContent);    if BCanFindTask then beginStrTempFileContent := Trim(StrTempFileContent); //去除字符串中起始和结束部分的空格和控制符Result := StrToInt(StrTempFileContent) > 0; //程序正在运行end;end;DelTree(StrTempFilePath, False, true, False); //删除临时文件if not BCanFindTask thenResult := False;
end;//调用该函数是,StrInfo 为检查到程序正在运行,询问是否先关闭程序提示
//无程序正在运行或选择关闭进程则返回 True,继续原来操作,否则返回 False
function CloseRunningDemo(StrInfo: String): Boolean;
varBFindTask, BCloseRunningDemo: Boolean;StrCmdKillTask: String;ResultCode: Integer;
beginBCloseRunningDemo := True;   BFindTask := FindTask();if BCanFindTask and BFindTask then beginBCloseRunningDemo := Msgbox(StrInfo, mbConfirmation, MB_YESNO or MB_DEFBUTTON1) = IDYES;if BCloseRunningDemo then begin //查找到进程,并选择关闭进程StrCmdKillTask := '/c taskkill /f /t /im '  + ExpandConstant('{#MyDemoExeName}');if not ShellExec('open', ExpandConstant('{cmd}'), StrCmdKillTask, '', SW_HIDE, ewWaitUntilTerminated, ResultCode) thenMsgBox('自动退出进程失败,请手动关闭软件后点击 "确定" 继续下一步操作', mbInformation, MB_OK);end;endelse if not BCanFindTask then beginMsgBox('查找 Demo 是否正在运行失败,请确保软件没有运行再点击 "确定" 继续下一步操作', mbInformation, MB_OK);end;Result := BCloseRunningDemo;
end;

查找进程命令:

#define MyDemoExeName "Demo.exe"  //进程名
StrTempFilePath := getCurrentDir() + '\findTaskTempFile.txt'; //将查找进程结果存放到临时文件
StrCmdFindTask := Format('/c tasklist|find /c /i "%s" > "%s"', [ExpandConstant('{#MyDemoExeName}'), StrTempFilePath]);
ShellExec('open', ExpandConstant('{cmd}'), StrCmdFindTask, '', SW_HIDE, ewWaitUntilTerminated, ResultCode)

参数说明:
第一个/c参数:执行字符串指定的命令然后中断;
find /c: 仅显示字符串的行数,这里如果查找到进程,则结果为1,没有则为0。
find /i:查找时忽略大小写
左边字符串"%s":查找的名字字符串
右边字符串> "%s":查找结果输出文件路径
{cmd}:系统标准命令解释器的完整路径名。Windows\System32\cmd.exe
SW_HIDE:不显示命令行窗口
ewWaitUntilTerminated:开启进程后阻塞,直到进程终止以后才返回
ResultCode:如果指定的文件已执行则返回 True,否则返回 False。如果返回 True 并且是 WaitUntilTerminated,那么 ResultCode 返回执行的文件的退出代码。如果返回 False,那么 ResultCode 指定遇到的错误。使用 SysErrorMessage(ResultCode) 获取错误描述。

关闭进程:

StrCmdKillTask := '/c taskkill /f /t /im '  + ExpandConstant('{#MyDemoExeName}');
ShellExec('open', ExpandConstant('{cmd}'), StrCmdKillTask, '', SW_HIDE, ewWaitUntilTerminated, ResultCode);

参数说明:
第一个/c参数:执行字符串指定的命令然后中断;
/f(force): 强制结束正在运行的进程。
/t (Tree kill): 终止指定的进程和任何由此启动的子进程。
/im(image Name): 进程名称 指定要终止的进程的映像名称。通配符 *可用来指定所有映像名。

1.2.2. 查找窗口名关闭进程

varWinHwnd: HWND;BCloseRunningDemo: Boolean;
beginWinHwnd := FindWindowByWindowName('Demo');//查找窗口名,返回窗口句柄if WinHwnd <> 0 then //找到符合的窗口名beginBCloseRunningDemo := Msgbox(info, mbConfirmation, MB_YESNO or MB_DEFBUTTON1) = IDYES; if BCloseRunningDemo then begin   //点击确认再次获取窗口句柄,因为可能此时已关闭窗口或者窗口句柄改变WinHwnd := FindWindowByWindowName('Demo');if WinHwnd <> 0 thenif PostMessage(WinHwnd, 16, 0, 0) = False then   // 退出主进程MsgBox('自动退出进程失败,请手动关闭软件后继续下一步操作', mbInformation, MB_OK);                 end;Result := BCloseRunningDemo;            end else beginResult := true;end
end;

检查程序是否正在运行通过查找窗口名,这样需保证查找的程序所有界面窗口名相同。

关闭进程是通过找到的窗口句柄,然后PostMessage发送消息来退出程序,存在以下问题:
1、多个窗口,尽管窗口名固定,但句柄不一样,可能查找时和点击关闭时句柄变化,导致关闭进程失败。
该问题可以通过选择关闭进程时再次获取窗口句柄解决。
2、PostMessage 的第二个参数为发送的消息,16WM_CLOSE,发送该消息后程序处理相当于点击程序的退出按钮,如果程序在一个子界面,退出后只是回到主界面,并未完全退出程序。
如果发送消息为WM_QUIT(18),程序无论在哪个界面均能退出,但MSDN说明不建议用PostMessage来发送WM_QUIT消息,PostMessage将消息发送到消息队列后就立即返回,这样可能未释放程序占用的资源。

程序关闭的过程为先收到WM_CLOSE消息,然后用 DestroyWindow函数,该函数完成窗口的清理工作,释放资源并发送WM_DESTROY消息。发送WM_DESTROY消息后会调用PostQuitMessage函数,该函数发送WM_QUIT造成GetMessage返回0来结束消息循环,从而终止程序。

1.2.3. 封装dll检测和关闭进程

网上常用的两个psvince.dllISTask.dll,可直接下载别人封装好的dll或自己封装。
XhmikosR/psvince

1.2.4. Inno Setup 脚本创建互斥量

[Setup]
DemoMutex=MyProgramsMutexName
[Code]
//用 CreateMutex 函数先创建互斥量
//再通过 CheckForMutexes 函数检查是否有互斥量

该方法如再安装时检测,则创建CreateMutex函数不能放在InitializeSetup函数中,否则开始安装时,即使无正在运行的程序,也会判断为有互斥量。
参考 Inno Setup安装程序单例运行说明。

用该方法在安装和卸载时检测不如第一种方便自定义为想要的效果。

1.3. 安装前检测程序已安装过

//安装前检查 有无旧版本
procedure UninstallOldVersion();
varStrSubKeyName1: String; StrSubKeyName2: String;StrUninstall: String;StrOldVersion: String;BUninstallOldVersion: Boolean;BSameVersion: Boolean;ResultCode: Integer;
beginStrSubKeyName1 := 'SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{1FE691F8-AD24-43CC-B5F7-78481C10D59A}}';StrSubKeyName2 := 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1FE691F8-AD24-43CC-B5F7-78481C10D59A}}';//检查是否已安装过相同软件if RegQueryStringValue(HKLM, StrSubKeyName1, 'UninstallString', StrUninstall)orRegQueryStringValue(HKLM, StrSubKeyName2, 'UninstallString', StrUninstall) thenbegin  //已安装过,检查版本号是否相同   RegQueryStringValue(HKLM, StrSubKeyName1, 'DisplayName', StrOldVersion);RegQueryStringValue(HKLM, StrSubKeyName2, 'DisplayName', StrOldVersion);                                              BSameVersion := StrOldVersion = ExpandConstant('{#MyDemoName} {#MyDemoVersion}');if BSameVersion then beginBUninstallOldVersion := MsgBox('已经安装过该版本的软件,是否继续?' #13#13 '选择 "是" 卸载软件再安装,选择 "否" 退出安装,是否继续?',mbConfirmation,MB_YESNO or MB_DEFBUTTON2) = IDYES;endelse beginBUninstallOldVersion := MsgBox('已经安装过该软件,必须先卸载 '#13#13'选择 "是" 卸载软件,选择 "否" 退出安装,是否继续?',mbConfirmation,MB_YESNO or MB_DEFBUTTON1) = IDYES;  end;if BUninstallOldVersion then //卸载旧版本Exec(RemoveQuotes(StrUninstall), '/silent', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)else //退出安装BContinueInstall := False  end;
end;

通过查找卸载注册表,之前设置AppId时创建的键,路径为HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{1FE691F8-AD24-43CC-B5F7-78481C10D59A}}_is1,查找UninstallString的值查看是否有相同名字程序未卸载,然后查看DisplayName的值得到未卸载程序的版本,与单签安装版本的版本比较,如果相同则提示。

如要继续安装软件,需先卸载已安装的软件,卸载是执行的安装文件夹中的卸载可执行文件,路径为UninstallString的值,因为该值包含引号,通过RemoveQuotes(StrUninstall)移除引号。/silent参数表示静默卸载,即卸载时不执行Inno Setup自带的“您确认完全删除Demo及他的所有组件吗?”消息框,直接开始卸载。

1.4. 卸载前确认是否备份数据

1.4.1. 卸载前检查

//卸载时先执行该函数,如返回 `True` 则继续卸载,返回`False`则终端卸载,可用该函数处理卸载前需检查的事
//这里卸载前先检查程序是否运行,如运行则需关闭再卸载,否则不能卸载干净,因此如选择不关闭程序则中断卸载。
function InitializeUninstall(): Boolean;
beginBContinueInstall := CloseRunningDemo('卸载程序检测到客户端正在运行' #13#13 '单击 “是” 关闭进程,继续卸载,或按 “否” 退出'); Result := BContinueInstall;
end;

1.4.2. 确认卸载后备份数据再卸载

确定开始卸载后,开始卸载过程,执行下面CurUninstallStepChanged过程,确认卸载后不可中断卸载。

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begincase CurUninstallStep ofusUninstall: //卸载前执行begin                                                                                              BNeedBackup := MsgBox('数据备份:' #13#13 '即将卸载软件,是否 "备份文件" 再卸载?' #13#13 '单击 "是" 备份数据, 或按 "否" 直接卸载', mbConfirmation, MB_YESNO or MB_DEFBUTTON1) = IDYES;if not BNeedBackup thenNoBackupVerification();  //选择 否 不备份,则二次确认if BNeedBackup thenUninstallBackup();end;      end;
end;

CurUninstallStep的种类有:

usDemoMutexCheck, usUninstall, usPostUninstall, usDone

各参数说明见Innosetup的状态页面和向导页面解释。
#13#13:用来换行。

1.4.3. 卸载时不备份数据进行身份验证

如选择不备份,则说明风险并需输入密码验证。

varForm: TSetupForm;PasswordEdit: TPasswordEdit;
// 输入密码 点击确认,密码正确则关闭窗口不备份数据,直接卸载
procedure CheckPasswordOKClick(Sender: TObject);
beginif PasswordEdit.Text = 'Demo' then beginBNeedBackup := False;Form.Close;endelse beginMsgBox('密码错误!', mbInformation, mb_Ok);end;
end;
// 输入密码 点击 取消 关闭窗口,点击取消或者关闭窗口则备份数据
procedure CheckPasswordCancelClick(Sender: TObject);
beginForm.Close;
end;//身份验证窗口
procedure NoBackupVerification();
var     DescriptionText: TNewStaticText;OKButton, CancelButton: TButton;W: Integer;
beginBNeedBackup := True; //关闭 窗口 相当于 取消 则备份Form := CreateCustomForm();   tryForm.ClientWidth := ScaleX(300);Form.ClientHeight := ScaleY(200);Form.Caption := '身份验证';DescriptionText := TNewStaticText.Create(Form);DescriptionText.Parent := Form;DescriptionText.Top := ScaleY(10);DescriptionText.Left := ScaleY(10);DescriptionText.Width := Form.ClientWidth - ScaleX(2);DescriptionText.AutoSize := True;DescriptionText.ShowAccelChar := False;DescriptionText.WordWrap := False;DescriptionText.Caption := '风险说明' #13#13 '请输入 "密码" 以验证身份' #13#13 '点击 "取消" 则备份数据再卸载';PasswordEdit := TPasswordEdit.Create(Form);PasswordEdit.Parent := Form;PasswordEdit.Top := DescriptionText.Top + DescriptionText.Height + ScaleY(23);PasswordEdit.Left := ScaleX(23);PasswordEdit.Width := ScaleX(200);PasswordEdit.Height := ScaleY(23);    PasswordEdit.Anchors := [akLeft, akTop, akRight];CancelButton := TButton.Create(Form);CancelButton.Parent := Form;CancelButton.Top := Form.ClientHeight - ScaleY(23 + 10);CancelButton.Left := Form.ClientWidth - ScaleX(75 + 50);CancelButton.Height := ScaleY(23);CancelButton.Anchors := [akRight, akBottom];        CancelButton.Caption := '取消';CancelButton.OnClick := @CheckPasswordCancelClick; //点击取消按钮时执行 CancelButton.Default := True;CancelButton.Cancel := True;OKButton := TButton.Create(Form);OKButton.Parent := Form;OKButton.Top := CancelButton.Top;OKButton.Height := ScaleY(23);OKButton.Left := Form.ClientWidth - ScaleX(75 + 6 + 75 + 50);OKButton.Anchors := [akRight, akBottom];OKButton.Caption := '确定';OKButton.OnClick := @CheckPasswordOKClick; //点击确定按钮时执行      W := Form.CalculateButtonWidth([OKButton.Caption, CancelButton.Caption]);OKButton.Width := W;CancelButton.Width := W;Form.ActiveControl := PasswordEdit;Form.KeepSizeY := True;Form.ShowModal();  //让窗口一直显示finally Form.Free();        end;
end;

创建身份验证窗口设置参考官方示例CodeClasses.iss

1.4.4. 备份数据

复制文件用 FileCopy函数,复制文件夹则需用windows命令:

//函数复制文件夹,参数为:旧文件夹路径,新文件夹路径,执行复制文件夹命令的.bat文件
function MoveFolder(StrOldFileDir, StrNewFileDir, BackupBatDir: String): Boolean;
varStrCmd: String;ResultCode: Integer;
beginif FileOrDirExists(StrOldFileDir) thenbeginStrCmd := 'xcopy /e/i/q '+ StrOldFileDir + ' ' + StrNewFileDir + #13#10;SaveStringToFile(BackupBatDir, StrCmd, False);//命令写入.bat文件中Exec(BackupBatDir, '', '', SW_HIDE, ewWaitUntilTerminated, ResultCode); //执行.bat文件Result := FileOrDirExists(StrNewFileDir);endelse beginResult := true;end
end;

1.4.5. 压缩文件夹

//压缩备份文件夹
StrCmd := 'call ' + DemoDir + '\zipjs.bat zipDirItems -source '+ BackupDir + ' -destination ' + BackupDir + '.zip' + ' -keep yes -force no';
SaveStringToFile(BackupBatPath, StrCmd, False);
Exec(BackupBatPath, '', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);

将文件夹压缩为.zip格式且不使用外部压缩工具,用到脚本文件为 zipjs.bat。
测试用该脚本压缩成功,即使系统未安装任何压缩工具。
压缩文件夹使用的方法:Using Shell.Application。
脚本调用语法:在命令行窗口定位到脚本所在的目录后,输入zipjs.bat,会有帮助文档说明。

1.5. 添加 readme 文件

想要程序在安装完成后打开一个 readme 文件,可在 [Files] 段添加,加上 isreadme 标志即可。

;readme.txt
Source: "{#OutPut}\readme.txt"; DestDir: "{app}"; Flags: isreadme replacesameversion

效果:在程序安装完成后,会有个勾选框选择是否查看 readme。
见帮助文档说明:

File is the “README” file. Only one file in an installation can have this flag.
When a file has this flag, the user will asked if he/she would like to view the README file after the installation has completed.
If Yes is chosen, Setup will open the file, using the default program for the file type.
For this reason, the README file should always end with an extension like .txt, .wri, or .doc.
Note that if Setup has to restart the user’s computer (as a result of installing a file with the flag restartreplace
or if the AlwaysRestart [Setup] section directive is yes), the user will not be given an option to view the README file.

1.6. 参考

1、Basic Pascal Tutorial
2、中文翻译语言文件
3、WOW6432Node
4、inno setup卸载时弹出意见反馈窗口和使用WinHttpRequest上传
5、注册表——Run、RunOnce 键值解析
6、常用批处理命令总结3之Find和FindStr
7、Windows 进程 Tasklist查看 与 Taskkill结束
8、Delphi 模式窗体返回值ModalResult的使用方法及注意事项
9、演示控件的 Anchors 属性
10、Delphi 常用属性说明(超长)
11、ShowModal() = mrOk
12、互联网软件的安装包界面设计-Inno setup
13、Inno Setup Translations
14、Innosetup的状态页面和向导页面解释
15、ShellExecuteA function (shellapi.h)
16、Inno Setup Help
17、How can I compress (/ zip ) and uncompress (/ unzip ) files and folders with batch file without using any external tools?

1.7 软件安装包

安装包百度网盘:Inno Setup 6.1.2 提取码:14k4

Inno Setup 打包脚本笔记相关推荐

  1. inno setup打包脚本总结

    inno setup是比较简单好用的一款打包工具. 下面以打包HelloWorld.exe为例进行说明. 一.打包目录的建立 创建source目录:用于放置主程序.依赖dll.资源等待打包文件. 创建 ...

  2. inno setup 打包脚本学习

    INNO SETUP 学习心得 1.脚本结构 1.[Setup] 段 这个段包括了安装和卸载程序所使用的全局设置,并且有些关键字在你建立的安装程序中是必须要用到的. 2.[Dirs] 段 这个段是可选 ...

  3. Inno setup 打包教程

    inno setup 是较常用且简单的软件打包工具. 1.安装并打开 inno setup 软件 ① 运行环境 系统:Windows 7 软件:inno setup 5.5.5 ② 安装 inno s ...

  4. Inno setup打包软件安装

    Inno setup打包软件特点是开源.简单.重点还是免费的. 软件下载官网 https://jrsoftware.org/isinfo.php 界面汉化包地址:https://jrsoftware. ...

  5. Inno Setup 打包发布exe程序的步骤及注意事项及解决发布后的exe解压后文件都在主目录下导致程序无法正常运行的问题

    目录 一.链接.exe文件的.dll动态链接库 1.1.可以利用QT官网提供的工具windeployqt 生成方式见如下: 1.2.使用脚本文件 二.使用绿色汉化版打包小程序inno setup5.5 ...

  6. inno setup打包软件学习

    目录 一  打包结果 二 示例打包脚本 三 错误解决 3.1 另一个程序正在使用此文件,进程无法访问 3.2 桌面图标无法修改 四 参考资料 一  打包结果 测试程序来自: 泽森科工 (zenuste ...

  7. inno setup打包程序安装出现CreateProcess failed;code 740

    问题: 使用inno setup打包我们发布的程序test.exe,在安装结束后,勾选了Launch xxx运行程序,然后出现如下报错: Unable to execute file:xxx Crea ...

  8. Inno setup打包vc++运行库

    windows下打包应用程序,基本都要依赖vc++运行库,打包工具使用的Inno setup,记录一下inno setup打包vc运行库的方法 下载地址 https://support.microso ...

  9. Inno Setup 打包的文件以管理员权限运行

    近期发现一个问题,就是Inno Setup打包的程序安装完成后运行需求管理员权限的程序的时候会失败( inno createprocess   需要提升),解决这个问题的最简单办法就是打包的后的程序也 ...

最新文章

  1. 这段时间Dot Text 老出错,实在没办法解决了,特来求助。[InvalidOperationException: 内部连接致命错误。]...
  2. android检测内存使用工具--procrank
  3. Keras之MLP:利用MLP【Input(8)→(12)(relu)→O(sigmoid+二元交叉)】模型实现预测新数据(利用糖尿病数据集的八个特征实现二分类预测
  4. 【MM模块】Procurement for Consumption Material 消耗性物料的采购流程
  5. 再见Spring Security!推荐一款功能强大的权限认证框架,用起来够优雅!
  6. Python3高级 之 协程
  7. 推荐一个js代码混淆工具的网址
  8. 各品牌智能电视刷机怎么寻找对应固件包?详细图文教程分享
  9. word表格转图片线条不会缺失方法
  10. oracle恢复删除的表
  11. 百度指数批量查询器,百度指数
  12. python电路仿真软件_4种电路仿真软件比较 - SmartLinkCloud,智联网云平台 - OSCHINA - 中文开源技术交流社区...
  13. 智课雅思词汇---六、fer是什么意思
  14. bzoj2827千山鸟飞绝(Treap)
  15. u盘有图标计算机显示没有,电脑没插u盘却显示u盘图标是怎么回事?
  16. java即时通讯源码 IM即时通讯源码 IM源码 安卓苹果原生APP源码 带音视频
  17. 广告刷屏世界杯,联想Filez助力海信全球营销运营
  18. Solidity介绍
  19. 光纤布线兵法之热点问题篇(二)
  20. 软件测试BUG(缺陷)等级分类

热门文章

  1. Paddle使用半监督式学习完成语句分类
  2. ZC706评估板学习--小白向(一)介绍与准备工作
  3. Spring笔记——装配Bean
  4. 榕树贷款分布式共识算法分为CFT与BFT(榕树贷款)
  5. [轉]mssql数据库简繁体互转
  6. 世界最牛芯片企业:每天净赚2亿,它不在美国,也不在日韩!
  7. VML实现的饼图(JavaScript类封装)
  8. PSP自制固件procfw编译 – 小问题汇总
  9. 基于Directshow架构的开源播放器和插件
  10. D3.js实现人物关系图谱有移动、拖拽、放大功能