本示例涉及:

程序的打包和数字签名

InnoSetup的快速上手

以及一个产品从编译到安装的过程演示

 

首先,我提供一份InnoSteup的脚本文件,小伙伴们可直接使用这个脚本进行打包(不过得修改一下相关的变量为你自己电脑上需要打包的内容)

; 脚本由 Inno Setup 脚本向导 生成!
; 有关创建 Inno Setup 脚本文件的详细资料请查阅帮助文档!

//创建一些在打包过程中可能会自定义变动的变量
#define MyAppName "安装包制作示范程序"
#define MyAppVerName "安装包制作示范程序·1.0.0.3"
#define MyAppGroupName "安装包制作示范程序"
#define MyAppPublisher "Eonsin_sky"
#define MyAppURL ""
#define MyAppExeName "CustomerMainExe.exe"
#define MyAppVersion "1.0.0.3"
#define MyLicensFile "F:\WorkSpace2.0\VSProject\CustomerWebProtocolHandler\用于打包的安装声明.txt"
#define MyOutputDir "F:\WorkSpace2.0\VSProject\CustomerWebProtocolHandler\RELEASE_PACKAGE"
#define MyOutputBaseFileName "安装包制作示范程序_Setup_1.0.0.3"
#define MyWizardImageFile "F:\WorkSpace2.0\VSProject\CustomerWebProtocolHandler\INSTALL_PACKAGE\icon\WizardImage.bmp" 
#define MyWizardSmallImageFile "F:\WorkSpace2.0\VSProject\CustomerWebProtocolHandler\INSTALL_PACKAGE\icon\WizardImageSmal.bmp" 
#define MySetupIconFile "F:\WorkSpace2.0\VSProject\CustomerWebProtocolHandler\INSTALL_PACKAGE\icon\main.ico" 
#define MyInstallPackageDir "F:\WorkSpace2.0\VSProject\CustomerWebProtocolHandler\INSTALL_PACKAGE"
#define MySignTools "mysigntools"

[Setup]
; 注: AppId的值为单独标识该应用程序。
; 不要为其他安装程序使用相同的AppId值。
; (生成新的GUID,点击 工具|在IDE中生成GUID。)
AppId={{C417BA22-36F9-44F8-B28B-CD4B3AD3499B}}
AppName={#MyAppName}
AppMutex={#MyAppExeName}
AppVerName={#MyAppVerName}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={commonpf}\{#MyAppName}
DefaultGroupName={#MyAppGroupName}
AllowNoIcons=true
LicenseFile={#MyLicensFile}
OutputDir={#MyOutputDir}
OutputBaseFilename=  {#MyOutputBaseFileName}
Compression=lzma/ultra64
SolidCompression=yes
InternalCompressLevel=ultra
VersionInfoCompany={#MyAppPublisher}
VersionInfoTextVersion={#MyAppVersion}
VersionInfoCopyright={#MyAppPublisher}
AppCopyright={#MyAppPublisher}
VersionInfoVersion={#MyAppVersion}
WizardImageFile={#MyWizardImageFile}
WizardSmallImageFile={#MyWizardSmallImageFile}
WizardImageStretch=true
SetupIconFile={#MySetupIconFile}
UsedUserAreasWarning=no
SignTool={#MySignTools}
SignedUninstaller=true

[Languages]
Name: Armenian; MessagesFile: compiler:Languages\Armenian.isl, compiler:Languages\Japanese.isl
Name: Japanese; MessagesFile: compiler:Languages\Japanese.isl, compiler:Languages\Armenian.isl

[Tasks]
Name: desktopicon; Description: {cm:CreateDesktopIcon}; GroupDescription: {cm:AdditionalIcons}; Flags: checkedonce checkablealone
Name: quicklaunchicon; Description: {cm:CreateQuickLaunchIcon}; GroupDescription: {cm:AdditionalIcons}; Flags: checkedonce checkablealone

[Files]
;Source: {#MyInstallPackageDir}\InsDll.dll; DestDir: {app}; Flags: ignoreversion
;Source: {#MyInstallPackageDir}\CustomerMainExe.exe; DestDir: {app}; Flags: ignoreversion
;Source: {#MyInstallPackageDir}\CustomerWebProtocolHandler.exe; DestDir: {app}; Flags: ignoreversion; Tasks: ; Languages: 
Source: {#MyInstallPackageDir}\*; DestDir: {app}; Flags: ignoreversion recursesubdirs createallsubdirs

[Icons]
Name: {group}\{#MyAppName}; Filename: {app}\{#MyAppExeName}
Name: {group}\{cm:UninstallProgram,{#MyAppName}}; Filename: {uninstallexe}
Name: {commondesktop}\{#MyAppName}; Filename: {app}\{#MyAppExeName}; Tasks: desktopicon
Name: {userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}; Filename: {app}\{#MyAppExeName}; Tasks: quicklaunchicon

[Run]
Filename: {app}\{#MyAppExeName}; Description: {cm:LaunchProgram,{#MyAppName}}; Flags: nowait postinstall skipifsilent runascurrentuser

[Registry]
Root: HKLM; Subkey: SOFTWARE\CustomerWebProtocolHandler; ValueType: string; Flags: uninsdeletekey; Tasks: ; Languages: ; ValueName: Version; ValueData: {#MyAppVersion}
Root: HKLM; Subkey: SOFTWARE\CustomerWebProtocolHandler; ValueType: string; ValueName: path; Flags: uninsdeletekey; ValueData: """{app}\{#MyAppExeName}"""; Tasks: 


[UninstallDelete]
Type: filesandordirs; Name: {app}
;Type: filesandordirs; Name: {app}\bins
;Type: files; Name: {app}\GPClient.db
;Type: files; Name: {app}\*.ini
;Type: files; Name: {app}\*.xml
;Type: files; Name: {app}\*.dat
;Type: files; Name: {app}\*.conf
;Type: files; Name: {app}\ASUpdateOld.EXE


[Code]
//声明函数,用于调用dll中的InstallInvok .只有在安装之后会调用
function InstallInvok(strProtocol: String; strProtocolHandleExe: String; nDefIconIndex: Integer) : Boolean;
external 'InstallInvok@files:InsDll.dll cdecl setuponly';

//声明函数,用于调用dll中的UnInstallInvok  .只有在卸载之后才会调用
function UninstallInvok(strProtocol: String; strProtocolHandleExe: String; nDefIconIndex: Integer) : Boolean;
external 'UninstallInvok@{app}\InsDll.dll cdecl uninstallonly';

//卸载的时候执行
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
  if CurUninstallStep = usUninstall then
  begin
   // MsgBox('uninstall begin', mbInformation, MB_OK);
    UninstallInvok('MyCustomerProtocol', ExpandConstant('{app}\CustomerWebProtocolHandler.exe'), -128);
    UnloadDLL(ExpandConstant('{app}\InsDll.dll'));
    //MsgBox('uninstall end', mbInformation, MB_OK);
  end
end;

//安装的时候执行
procedure CurStepChanged (CurStep: TSetupStep );
begin
  if CurStep = ssDone then
  begin
    //MsgBox('installation is done'+ExpandConstant('{app}\CustomerWebProtocolHandler.exe'), mbInformation, MB_OK);
    InstallInvok('MyCustomerProtocol', ExpandConstant('{app}\CustomerWebProtocolHandler.exe'), -128);
  end;
end;

为了方便你理解,我提供了一个压缩包,里面包含了这次示例说需要的【VS项目】、【InnoSetup安装包】、【相关的签名工具】、【数字签名相关的测试证书】

从此处获取--->

度盘链接: https://pan.baidu.com/s/1dO6ZkI9oOIe5NnNzRW2zUg 提取码: 9gv7

现在开始讲解。

1、编译Release工程,这时候在项目目录下会生成我们需要打包的相关文件

inno打包 onlyifdoesntexist inno打包需要密码函数_打包

图1,编译项目生成的文件

其中CustomerMainExe.exe是我们的主程序,CustomerWebProtocolHandler.exe则是我们的协议处理程序(当在浏览器中输入我们自定义的协议的时候系统就会自动调用这个程序,类似输入磁力链接自动启用迅雷下载)

InsDll.dll是封装了一些我们安装程序之后的操作供InnoStep安装程序或其他程序调用。

 

2.安装InnoSetup程序打开我一开始就分享的打包脚本,并将脚本中包含打包项目路径的地方改成你自己电脑上的路径。替换完毕之后按Ctrl+F9进行打包也可以点击下图所示按钮进行打包。

inno打包 onlyifdoesntexist inno打包需要密码函数_程序打包_02

图2,进行打包

生成的安装包位于【VS项目】的“RELEASE_PACKAGE”目录下。

 

3.(可选)2步骤虽然执行了打包操作但是我们的程序并没有被签名,没有数据签名的文件是无法在网上合法发布的哦。所以这一步说明如何在打包的同时进行数字签名。

首先在InnoSetup中打开tool->configure sign tools...如图所示

inno打包 onlyifdoesntexist inno打包需要密码函数_程序打包_03

图3,打开签名工具配置页

 

得到如配置框

inno打包 onlyifdoesntexist inno打包需要密码函数_安装包制作_04

图4,签名工具配置框

选择add,输入mysigntools,接下来在配置框中输入运行签名工具的启动参数:

$qF:\WorkSpace2.0\VSProject\CustomerWebProtocolHandler\签名工具\signtool.exe$q sign /f $qF:\WorkSpace2.0\VSProject\CustomerWebProtocolHandler\签名工具\测试证书\eosin_sky.pfx$q /p "123" /t $qhttp://timestamp.comodoca.com/authenticode$q $f

这里我贴的启动参数是基于我电脑上的演示所用的【VS项目】所在路径,各位在配置这里的时候需要改成你机子上对应的路径。

配置完签名工具之后推出配置框,接下来在安装脚本的[Setup]段找到SignTool字段:

inno打包 onlyifdoesntexist inno打包需要密码函数_inno setup_05

图5,签名工具字段

 

可见这个字段的值是变量MySignTools:

inno打包 onlyifdoesntexist inno打包需要密码函数_数字签名_06

图6,签名工具变量

该变量的值就是我们刚刚配置的签名工具的值。

做好上述步骤之后我们再打包一下即可将我们要发布的文件进行数字签名并打包:

inno打包 onlyifdoesntexist inno打包需要密码函数_inno setup_07

图7,打包并且签名

进过上述步骤我们就完成了安装包的打包。


进过上述步骤之后我们就完成了安装包的制作,接下来我们看看对程序进行安装

打开安装进行安装

inno打包 onlyifdoesntexist inno打包需要密码函数_数字签名_08

图8,打开安装包

 

由于官方InnoSetup安装包不提供简体中文所以我配置的是日语,如果需要配置简体中文则可以自行下载语言文件“ChineseSimp.isl”到Inno Setup根目录中的Languages文件夹

然后在安装脚本文件中的[Languages]段进行修改就好

inno打包 onlyifdoesntexist inno打包需要密码函数_数字签名_09

图9,语言文件所在目录

inno打包 onlyifdoesntexist inno打包需要密码函数_打包_10

图10,配置语言

 

当我们同意安装之后会进入是否同意声明的界面

inno打包 onlyifdoesntexist inno打包需要密码函数_inno setup_11

图11,声明界面

如果不同意则会退出安装,所以我们需要点击同意,这里显示的声明文件是我们【VS工程】目录下的“用于打包的安装声明.txt”文件

我们继续往后:

inno打包 onlyifdoesntexist inno打包需要密码函数_数字签名_12

图12,选择安装路径

inno打包 onlyifdoesntexist inno打包需要密码函数_数字签名_13

图13,询问是否将程序pin到开始菜单

inno打包 onlyifdoesntexist inno打包需要密码函数_打包_14

图14,询问是否生产快捷方式、是否自启动

inno打包 onlyifdoesntexist inno打包需要密码函数_打包_15

图15,确认安装步骤

 

inno打包 onlyifdoesntexist inno打包需要密码函数_程序打包_16

图16,安装成功

 

这时候选择启动示例程序主程序,由我们的安装脚本可知,

#define MyAppExeName "CustomerMainExe.exe"

...
..
...

[Run]
Filename: {app}\{#MyAppExeName}; Description: {cm:LaunchProgram,{#MyAppName}}; Flags: nowait postinstall skipifsilent runascurrentuser

图17,安装完成之后启动主程序相关代码段

 

这个程序是"CustomerMainExe.exe"

点击完成,之后启动“CustomerMainExe.exe”

inno打包 onlyifdoesntexist inno打包需要密码函数_安装包制作_17

图18,示例主程序正在运行

 

这时候我们的主程序是在模拟运行了, 它在等待有自定义链接被触发(相当于是迅雷打开了,但没人输入磁力链接)

这时候我们完成大半了,接下来我们在浏览器中输入自定义协议“mycustomerprotocol:///hello&evertyone” (注, 为什么是mycustomerprotocol:/// 的格式?我后面会讲到)

inno打包 onlyifdoesntexist inno打包需要密码函数_打包_18

图19,输入自定义协议

系统会提示我们是否启动“CustomerWebProtocolHandler.exe”程序来处理这个协议(注,为什么系统会自动运行我们的程序?我后面会讲到)

inno打包 onlyifdoesntexist inno打包需要密码函数_程序打包_19

图20,触发自定义协议处理程序

 

我们“CustomerWebProtocolHandler.exe”这个程序是实现了接受自定义协议并将这个协议传输给我们的主程序去处理(如果主程序未启动则启动主程序并处理,但我这里未实现启动主程序功能)的功能。

让我们选择“Yes”启动“CustomerWebProtocolHandler.exe”

inno打包 onlyifdoesntexist inno打包需要密码函数_数字签名_20

可以看到我们的协议处理程序“CustomerWebProtocolHandler.exe”已经把协议转发给主程序处理,

至此我们就模拟了整个程序的用法。

 

接下来让我们看看我们为什么输入“mycustomerprotocol:///”格式的指令系统就能识别到?

因为我们的安装程序在安装完毕之后调用了我们的InsDll.dll中的InstallInvok函数,将这个协议注册给了“CustomerWebProtocolHandler.exe”来处理

相关带脚本代码段:

[Code]
//声明函数,用于调用dll中的InstallInvok .只有在安装之后会调用
function InstallInvok(strProtocol: String; strProtocolHandleExe: String; nDefIconIndex: Integer) : Boolean;
external 'InstallInvok@files:InsDll.dll cdecl setuponly';

//声明函数,用于调用dll中的UnInstallInvok  .只有在卸载之后才会调用
function UninstallInvok(strProtocol: String; strProtocolHandleExe: String; nDefIconIndex: Integer) : Boolean;
external 'UninstallInvok@{app}\InsDll.dll cdecl uninstallonly';

//卸载的时候执行
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
  if CurUninstallStep = usUninstall then
  begin
   // MsgBox('uninstall begin', mbInformation, MB_OK);
    UninstallInvok('MyCustomerProtocol', ExpandConstant('{app}\CustomerWebProtocolHandler.exe'), -128);
    UnloadDLL(ExpandConstant('{app}\InsDll.dll'));
    //MsgBox('uninstall end', mbInformation, MB_OK);
  end
end;

//安装的时候执行
procedure CurStepChanged (CurStep: TSetupStep );
begin
  if CurStep = ssDone then
  begin
    //MsgBox('installation is done'+ExpandConstant('{app}\CustomerWebProtocolHandler.exe'), mbInformation, MB_OK);
    InstallInvok('MyCustomerProtocol', ExpandConstant('{app}\CustomerWebProtocolHandler.exe'), -128);
  end;
end;

通过这个代码段我们的安装程序就会在安装之后调用InsDll.dll中的InstallInvok来注册协议,卸载的时候会调用UnInstallInvok来注销协议。

我们也可以不用MyCustomerProtocol这种协议,只需要在代码段中把协议的名字改成其他即可处理对应的协议。

 

当我们通过安装程序卸载程序的时候会注销我们的协议,这时候在浏览器中输入协议就无效了。

inno打包 onlyifdoesntexist inno打包需要密码函数_数字签名_21

 

好了,到这里我们就完成了安装包的制作了!!!