Innosetup打包工具,从工具安装到脚本编写到打包发布

前言
平常我们给电脑安装微信,QQ,钉钉等工具,都是需要去下载这个工具的安装包,进行安装。这些安装包都是由一些打包工具制作而成。常见的打包工具有:NSIS ,Innosetup,VS自带的打包工具,Install Shield等等。这些工具各有优劣,其中Innosetup算是使用量比较大的一种,所以本次本文专门介绍一下Innosetup这个打包工具的使用。
1.介绍
Innosetup是Windows下生成exe安装包的一个很实用的打包工具,用Delphi写成,作为一款用户量很大打包工具,Inno Setup其主要优点有:免费的安装制作软件,小巧、简便、精美,支持pascal脚本。
要说明Innosetup的打包程序,得先了解exe程序到底是个什么。
exe是可执行文件(Executable File)的缩写,程序实际上是个二进制可执行程序,它包含了程序的代码和资源,可以在Windows操作系统中直接运行。
exe文件的主要作用是启动程序,用户通过双击文件即可运行相应的程序。此外,exe文件还可能包含安装程序,用于在用户计算机上安装软件(这就是我们用Innosetup打包的原因)。这种exe安装包,你甚至可以将他理解成一个压缩包,安装包安装的过程,实际上是个解压释放资源的过程。
2.工具安装
Innosetup工具有比较多的版本,但都比较早了,目前比较流行的是5.5左右的版本。但有些比较好的增强版,可以做一些自定义的,比较酷炫的安装页面。
Innosetup增强版安装包下载
下载后,直接双击安装,一路下一步即可。
安装完之后要注意,如果你的安装包是来自其他地方下载的,要检查下Inno Setup一些汉化版存在的管理员权限不生效的问题。你可以安装后,用ResourceHacker.exe工具打开安装目录下的“SetupLdr.e32”文件,检查清单里的"requestedExecutionLevel"字段,如果不是““requireAdministrator””,则要改为"requireAdministrator";这样安装包脚本设置安装包拥有管理员权限才会生效。当然你也可以先不管,先做一个带管理员权限的安装包去试试,如果没有成功带上权限再去修改。
安装后打开大致是这样的:
在这里插入图片描述

3.制作安装包
(1)用向导制作:对于初学者,可以使用上图中的向导来生成一个,基本上只要你各项填写无误,就能做一个最简单的安装包。向导是生成一个基本的安装包制作框架。
这里就简单截图给大家看看
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
其他的自己斟酌填入,最后向导制作脚本完成
在这里插入图片描述
你可以直接点击菜单栏的 “构建”->“编译”,就会生成一个.exe的安装包,安装包里包含你打进去的主程序和依赖库,可以用于给到用户安装使用。
(2)脚本制作:前面说的是向导生成,有时候很难根据自己的特定需要来制作安装包,现在介绍自己编写修改脚本来完成安装。Inno Setup是使用类pascal语言的脚本,所以多少得了解下这类语法,建议可以拿别人的脚本来改,一边改着一边熟悉,慢慢就了解一些关键字和语法了。
这里先大概说一些基本的语法:
“;”用来表示注释
“#”一些宏定义
[Setup]这种带中括号的,就是一些分类字段

;Innosetup的脚本
[Setup]
;指定安装包的各种基本属性
[Languages]
;指定文字的语言翻译文件
[dirs]
;指定需要创建的目标目录
[Files]
;指定放在安装包里面的文件,源文件在哪,目标目录在哪
[Registry]
;安装过程中要修改的注册表
[Run]
;安装过程中需要执行的操作,一些子安装包就在这里执行安装
[UninstallRun]
;卸载过程中需要执行的操作
[Code]
;在安装过程中需要执行的代码块和操作

其中[Setup]一些属性说明如下

[Setup]
;指定应用的ID,你可以网上在线生成一个GUID,记住每个安装包的AppId不能一样
AppId={{12345678-ABCD-4AC3-9C9D-2A3B4C5D6A7}
;指定应用的名称
AppName="MyApp"
;指定应用锁
AppMutex=Mutex
;指定应用的版本号
AppVersion="1.0.0.1"
;指定应用的发布者
AppPublisher="qianniulaoren"
;指定应用的网络地址
AppPublisherURL="www.xxxx.com"
;网络支持地址和更新地址
AppSupportURL=""
;默认安装目录
DefaultDirName="C:\\"
DirExistsWarning=no
DefaultGroupName=""
;输出安装包的名称
OutputBaseFilename="MyAppPackage_setup"
;压缩方式
Compression=lzma
SolidCompression=yes
WizardStyle=modern
;资源文件的目录
SourceDir = resource
;输出目录
OutputDir = ..\output
;是否需要管理员权限
PrivilegesRequired=admin
;图标
SetupIconFile=logo.ico
;是否允许无图标
AllowNoIcons=yes

对于一些不了解的字段,可以在Innosetup的帮助里查找其作用和含义,帮助文档还是比较丰富的。
这里先贴一个实际使用的脚本,修改成样例,附带说明来解释。

; 脚本由 Inno Setup 脚本向导 生成!
;定义变量产品名称
#define MyAppName "产品名称"
;定义变量安装包版本
#define MyAppVersion "1.3.6.1"
;定义变量产品描述
#define MyAppDescription  "YYYY Product Tool"
;定义变量所在公司
#define MyAppPublisher "深圳市xxxxx有限公司"
;定义变量公司网址
#define MyAppURL "http://www.xxxxxxxx.com/"

[Setup]
; 注: AppId的值为单独标识该应用程序。
; 不要为其他安装程序使用相同的AppId值。
; (若要生成新的 GUID,可在菜单中点击 "工具|生成 GUID")
; 下面这些字段,可以在Innosetup的帮助里查找其作用和含义
AppId={{52E3764D-C7C4-4F6C-87EE-29F34E51285C}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppCopyright=深圳市xxxx有限公司, Copyright (C) Inc.
VersionInfoVersion={#MyAppVersion}
VersionInfoTextVersion={#MyAppVersion}
VersionInfoDescription={#MyAppDescription}
DefaultDirName={pf}\QNLR\{#MyAppDescription}
DefaultGroupName=xxxx
DisableDirPage=yes
DisableProgramGroupPage=yes
DisableStartupPrompt=yes
RestartIfNeededByRun=no

; 管理员权限
PrivilegesRequired=admin
;打的包输出目录
OutputDir=.\output
;包的名称
OutputBaseFilename=YYYY_v{#MyAppVersion}
;打的包上的logo
SetupIconFile=SourceFile\icon\logo.ico
Compression=lzma
SolidCompression=yes
WizardStyle=modern

[Types]
;Name: "FULL";   Description: "完全安装"; 
;Name: "custom"; Description: "自定义安装"; Flags: iscustom
Name: "XXXX";   Description: "默认安装";


[Components]
;定义一些标识
Name: "driver";      Description: "深圳xxxx驱动";   Types: YYYY; Flags: fixed 
Name: "client";      Description: "YYYY工具客户端";           Types: YYYY; Flags: fixed

[Languages]
;语言
Name: "chinesesimp"; MessagesFile: "compiler:Default.isl"

[Tasks]
;Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked

[Files]
;这个很重要,这是一个辅助卸载的库,卸载时要调用这个库,下面的写法:Source源文件的目录,DestDir安装后释放目标目录
Source: "SourceFile\Exinterface.dll";  DestDir: "{app}\Exinterface"; Flags:ignoreversion overwritereadonly uninsremovereadonly;
;下面开始添加各个依赖库
Source: "SourceFile\mfc10\*"; DestDir: "{app}"; Flags: ignoreversion overwritereadonly uninsremovereadonly;
Source: "SourceFile\files\driver\*"; DestDir: "{app}\driver\"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: driver

;看看这个,后面有个Check判断,如果是64位系统则安装
Source: "SourceFile\files\x64\*"; DestDir: "{app}\x64\"; Flags: IgnoreVersion overwritereadonly uninsremovereadonly; Check: IsWin64();

;qt库文件
Source: "SourceFile\qtdll\*";    DestDir: "{app}"; Flags: recursesubdirs createallsubdirs;
Source: "SourceFile\mfc14\*"; DestDir: "{app}"; Flags: ignoreversion overwritereadonly uninsremovereadonly; 


;添加主程序
Source: "SourceFile\MyApp.exe"; DestDir: "{app}"; Flags: IgnoreVersion overwritereadonly uninsremovereadonly; Components: client; Check: IsWin7Version();
;添加一个子安装包
Source: "SourceFile\childPackage.exe"; DestDir: "{app}"; Flags: IgnoreVersion overwritereadonly uninsremovereadonly; Components: client; Check: IsWin7Version();
;这个用以说明,目标文件可以放在你想放置的任何目录,而不必与其他文件都放在一起
;Source: "SourceFile\Config.ini"; DestDir: "{userdocs}\..\AppData\Local\{#MyAppDescription}"; Flags: IgnoreVersion overwritereadonly uninsremovereadonly; Components: client 


[Icons]
;设置图标
Name: {commondesktop}\YYYY工具; Filename: {app}\MyApp.exe; Components: client 
Name: {group}\MyApp; Filename: {app}\MyApp.exe; Components: client 

;注册表
[Registry]
;软件版本
Root: HKLM; SubKey: "Software\Microsoft\Windows\CurrentVersion\Run";  ValueType: string; ValueName: "MyApp";   
;设置开机启动
ValueData: """{app}\MyApp.exe"" /autostart"; Flags:deletevalue noerror uninsdeletekey;


[Run]
;这段很重要,有些安装包里边还有子安装包,子安装包的安装就在这里执行安装,注意下面这个“-s”这就是我们常说的静默参数,下面这行意思是安装这个供应商的驱动子包,安装的时候,使用静默安装,就是界面上看不出来,类似后台运行的方式
;Filename: "{app}\childPackage.exe"; Flags:runhidden; Parameters:"-s"; Description: "供应商的驱动子包"; Components: childPackage


[UninstallRun]
;一些插件在卸载时要反注册
Filename: regsvr32; Parameters: "/u ""{app}\xxxxocx.ocx"" /s";
Filename: regsvr32; Parameters: "/u ""{app}\xxxxCOM.dll"" /s";


[UninstallDelete]
Name: "{app}";  Type: filesandordirs; 


[Code]
;这里是自定义的一些函数,你比如要判断是否64位系统呀,是否老版本呀,可以做一个函数,在其他地方调用
function KillProcessFromName(szValue:AnsiString): Boolean;
external 'KillProcessFromName@files:Exinterface.dll stdcall setuponly';

function IsModuleRun(szValue:AnsiString): Boolean;
external 'IsModuleRun@files:Exinterface.dll stdcall setuponly';

function unIsModuleRun(szValue:AnsiString): Boolean;
external 'IsModuleRun@{app}\Exinterface\Exinterface.dll stdcall uninstallonly';
 
function unKillProcessFromName(szValue:AnsiString): Boolean;
external 'KillProcessFromName@{app}\Exinterface\Exinterface.dll stdcall uninstallonly'; 

function UnInitializeOldVersion() : Boolean;
var  
  ResultStr: String;  
  ResultCode: Integer; 
begin  
  if RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{52EAB6ED-B6ED-B6ED-B6ED-29F4B6ED285C}_is1', 'UninstallString', ResultStr) then  
    begin
      ResultStr := RemoveQuotes(ResultStr);  
      Exec(ResultStr, '/VERYSILENT /SP- /NORESTART', '', SW_HIDE, ewWaitUntilTerminated, ResultCode); 
      Sleep(1000);
    end;   
    result := true;  
end;

procedure CurPageChanged(CurPageID: Integer); 
var
ErrorCode: Integer;
begin
  if (CurPageID = wpPreparing) OR (CurPageID = wpInstalling) then
    begin
      UnInitializeOldVersion();
    end;    
end;
;这里很重要,这是安装时下一步下一步的页面跳转,你可以卡在某一步做一些你要处理的操作
procedure CurStepChanged (CurStep: TSetupStep );
var
ErrorCode: Integer;
begin
   if CurStep = ssInstall  then
      begin
      ;如果旧版本的卸载程序存在,就先执行卸载
        if FileExists(ExpandConstant('{pf}\xxxx\YYYY\uninstall.exe')) then
          begin
              Exec( ExpandConstant ('{pf}\xxxx\YYYY\uninstall.exe'), ' /U:Uninstall/uninstall.xml /S','', SW_HIDE, ewWaitUntilTerminated, ErrorCode) ;
          end;
      end;
   if CurStep = ssDone then
    begin
    ;安装完就开启主程序
        ShellExec('open', ExpandConstant('{app}\MyApp.exe'), '-open 1', '', SW_SHOW, ewNoWait, ErrorCode);        
     end; 
end;


procedure CurUninstallStepChanged (CurUninstallStep: TUninstallStep ); 
var
strFilePath :String;
ErrorCode: Integer;
begin
    if CurUninstallStep = usPostUninstall then
      begin
        strFilePath  := ExpandConstant('{app}\Exinterface\Exinterface.dll');  
        UnloadDLL(strFilePath) ; 
      end;
    if CurUninstallStep = usUninstall then
      begin 
     ;安装时,如果程序或者一些后台的服务正在运行,必须要先杀死,不然没法安装替换

          unKillProcessFromName('server.exe'); 
          unKillProcessFromName('sb.exe');
          ;如果前面的子安装包也是要卸载替换,就在这卸载
          if FileExists(ExpandConstant('{pf}\child\uninst.exe')) then
            begin
              Exec( ExpandConstant ('{pf}\child\uninst.exe'), '-s','', SW_HIDE, ewWaitUntilTerminated, ErrorCode);
            end;
      end;
      if CurUninstallStep = usDone then
        begin
        ;有些是需要直接删除的,就直接删掉
          DelTree(ExpandConstant('{pf}\dddd\abcd.txt'), True, True, True);  
          DelTree(ExpandConstant('{pf}\gggg'), True, True, True); 
        end;
end;

procedure InitializeWizard ();
var
LabelDate: Tlabel;
begin
   CreateMutex('{#MyAppName}');

   WizardForm.WelcomeLabel2.Autosize := true;
   LabelDate := Tlabel.Create(WizardForm);
   LabelDate.Autosize := true;    
   LabelDate.Parent := WizardForm.WelcomePage;
   LabelDate.Left := WizardForm.WelcomeLabel2.Left;
   LabelDate.Top := WizardForm.WelcomeLabel2.Top +WizardForm.WelcomeLabel2.Height +80;
end;

function IsWinXPVersion() : Boolean;
var  
Version:TWindowsVersion;
begin  
  GetWindowsVersionEx(Version);
  if (Version.Major = 5) AND (Version.Minor = 1) then
    begin
    result := true;
    end
  else
    begin
    Result := false;
    end;
end;

function IsWin7Version() : Boolean;
var  
Version:TWindowsVersion;
begin  
  GetWindowsVersionEx(Version);
  if Version.Major > 5 then
    begin
    result := true;
    end
  else
    begin
    Result := false;
    end;
end;

以上算是一个比较规范点的打包脚本,可以直接拿去修改使用。
脚本写好之后,跟上面一样,就是点击“构建”->“编译”,生成你需要的安装包,将安装包交付客户,大功告成。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牵牛老人

码字不易,您的支持就是动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值