最近安排我弄程序的打包工作,然后叫我接触Inno Setup打包软件。
说实话,第一次弄,什么都不懂,就不断Baidu,当然很多都没有,只有看文档了!
前面打包程序部分都还好,都完成了,但是后来说要捆绑组建,这个可把我难住了,最开始我是把组建添加进去,然后安装程序后启动组建安装,这样的缺陷多的数不清。
而后,把组建捆绑到tmp中安装,但是也是存在问题,因为用户要是在安装过程中取消了,那自己的程序也没法跑了!
而后又加入了组建的安装检测,在最后一步的时候检测是否正确安装(通过扫描注册表),假如成功则完成,假如不成功则启动程序删除!
这样基本解决了,但是感觉好麻烦,好累赘!
而后又想到了,为什么不在开始就检测呢,如果没有则安装,安装失败则退出整个程序安装!
而后就开始了我的一点点的改动,完成。
最后代码如下:
[Files] Source: "NET2.exe"; DestDir: "{tmp}"; Flags: ignoreversion
[code] function NeedInstallDotNet(): Boolean; var success: boolean; install: cardinal; begin success := RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v2.0.50727', 'Install', install); Result := not(success and (install = 1)); end; function InitializeSetup(): Boolean; var ResultCode: Integer; begin Result :=true; if (NeedInstallDotNet) then begin MsgBox('您的电脑需要先安装Microsoft .NET Framework 2.0 SP2组建.' + #13 + '请等待组建加载完成并完成组建安装后再进行程序的安装.',mbError, MB_OK); ExtractTemporaryFile('NET2.exe'); Exec(ExpandConstant('{tmp}\NET2.exe'), '', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode); end; if (NeedInstallDotNet) then begin MsgBox('您的组建安装失败,程序将退出安装.',mbError, MB_OK); Result :=false; //安装程序退出 end else begin Result :=true; //安装程序继续 end; end;
完整的项目:
; Script generated by the Inno Setup Script Wizard. ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyCompany "Broadinter" #define MyAppName "Prober" #define MyAppVersion "3.0.0" #define MyAppPublisher "Broadinter, Inc." #define MyAppURL "http://www.broadinter.com/" #define MyAppId "{55E402DD-B073-4CDF-8AA7-D52FDC5B348E}" #define MyAppServeKiwi "kiwi.exe" #define MyAppServeWatchdog "kiwi_watchdog.exe" #define MyFormationDotNetName "NetFx20SP2_x86.exe" [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={{#MyAppId} AppName={#MyAppName} AppVersion={#MyAppVersion} AppPublisher={#MyAppPublisher} AppPublisherURL={#MyAppURL} AppSupportURL={#MyAppURL} AppUpdatesURL={#MyAppURL} AppCopyright=Copyright (C) 2013 {#MyAppPublisher} DefaultDirName={pf}\{#MyCompany} DefaultGroupName={#MyCompany} AllowNoIcons=yes LicenseFile=eula.rtf OutputDir=..\Setup OutputBaseFilename=setup SetupIconFile=setup.ico Compression=lzma SolidCompression=yes PrivilegesRequired=admin WizardImageFile=Image.bmp WizardSmallImageFile=SmallImage.bmp [Languages] Name: "chinesesimplified"; MessagesFile: "ChineseSimplified.isl" [Files] Source: "..\Source\Prober\*"; DestDir: "{app}\Prober"; Flags: ignoreversion recursesubdirs createallsubdirs; Source: "..\Source\Selections\network.conf"; DestDir: "{app}\Prober"; Flags: ignoreversion onlyifdoesntexist uninsneveruninstall; Check: NeedInstallNetworkConfig; Source: "..\Source\Selections\probe.conf"; DestDir: "{app}\Prober"; Flags: ignoreversion onlyifdoesntexist uninsneveruninstall; Check: NeedInstallProbeConfig; AfterInstall: MyAfterInstall; Source: "..\Source\Prober_Update\*"; DestDir: "{app}\Prober_Update"; Flags: ignoreversion recursesubdirs createallsubdirs; Source: "..\Source\Prober_Watchdog\*"; DestDir: "{app}\Prober_Watchdog"; Flags: ignoreversion recursesubdirs createallsubdirs; Source: "..\Source\Selections\NetFx20SP2_x86.exe"; DestDir: "{tmp}"; Flags: ignoreversion; Check: NeedInstallDotNet; Source: "..\Source\Selections\IE8-WindowsServer2003-x86-CHS.exe"; DestDir: "{tmp}"; Flags: ignoreversion; Check: NeedInstallIE; Source: "..\Source\Selections\Flashplayer11_7r700_202_winax.exe"; DestDir: "{tmp}"; Flags: ignoreversion; Check: NeedInstallFlash; [Run] Filename: "{app}\Prober\{#MyAppServeKiwi}"; Parameters: "-i Prober"; WorkingDir: "{app}\Prober"; StatusMsg: "正在安装Prober服务..."; BeforeInstall: BeforeInstallDelete; Filename: "{app}\Prober\{#MyAppServeKiwi}"; Parameters: "-s Prober"; WorkingDir: "{app}\Prober"; StatusMsg: "正在开启Prober服务..." Filename: "{app}\Prober_Watchdog\{#MyAppServeWatchdog}"; Parameters: "-i Prober_Watchdog"; WorkingDir: "{app}\Prober_Watchdog"; StatusMsg: "正在安装Prober_Watchdog服务..." Filename: "{app}\Prober_Watchdog\{#MyAppServeWatchdog}"; Parameters: "-s Prober_Watchdog"; WorkingDir: "{app}\Prober_Watchdog"; StatusMsg: "正在开启Prober_Watchdog服务..." Filename: "{tmp}\IE8-WindowsServer2003-x86-CHS.exe"; Parameters: " "; WorkingDir: "{tmp}"; StatusMsg: "正在安装IE8..."; Check: NeedInstallIE Filename: "{tmp}\Flashplayer11_7r700_202_winax.exe"; Parameters: "/install"; WorkingDir: "{tmp}"; StatusMsg: "正在安装Flashplayer11..."; Check: NeedInstallFlash [UninstallRun] Filename: "{app}\Prober\{#MyAppServeKiwi}"; Parameters: "-p Prober"; WorkingDir: "{app}\Prober"; StatusMsg: "正在停止Prober服务" Filename: "{app}\Prober\{#MyAppServeKiwi}"; Parameters: "-u Prober"; WorkingDir: "{app}\Prober"; StatusMsg: "正在卸载Prober服务" Filename: "{app}\Prober_Watchdog\{#MyAppServeWatchdog}"; Parameters: "-p Prober_Watchdog"; WorkingDir: "{app}\Prober_Watchdog"; StatusMsg: "正在停止Prober_Watchdog服务" Filename: "{app}\Prober_Watchdog\{#MyAppServeWatchdog}"; Parameters: "-u Prober_Watchdog"; WorkingDir: "{app}\Prober_Watchdog"; StatusMsg: "正在卸载Prober_Watchdog服务" [Code] var //探针配置页面 UserPage: TInputQueryWizardPage; //是否运行了卸载 IsUninstallRuned: Boolean; //是否保存配置文件 IsSaveConfig: Boolean; //配置属性 ConfigBool: Boolean; //CheckBox CB_IE: TNewCheckBox; CB_Flash: TNewCheckBox; {--检检测是否已经安装软件--} function CheckHaveApp(): Boolean; var ResultStr: String; ResultCode: Integer; begin if RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{#MyAppId}_is1', 'UninstallString', ResultStr) then begin if (MsgBox('检测到你已安装本软件,是否卸载?', mbConfirmation, MB_YESNO) = IDYES) then begin ResultStr := RemoveQuotes(ResultStr); Exec(ResultStr, '/silent', '', SW_HIDE, ewWaitUntilTerminated, ResultCode); //二次检测是否卸载 if RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{#MyAppId}_is1', 'UninstallString', ResultStr) then begin result:=false; end else begin result:=true; end; end; end else begin result:=true; end; end; {--检测是否需要安装NET组建--} function NeedInstallDotNet(): Boolean; var success: boolean; install: cardinal; begin success := RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v2.0.50727', 'Install', install); Result := not(success and (install = 1)); end; {--检测是否需要IE组建--} function NeedInstallIE(): Boolean; begin Result := CB_IE.Checked; end; {--检测是否需要Flash组建--} function NeedInstallFlash(): Boolean; begin Result := CB_Flash.Checked; end; {--检测是否需要安装Network配置文件--} function NeedInstallNetworkConfig(): Boolean; begin if FileExists(ExpandConstant('{app}') + '\Prober\network.conf') then begin Result := False; end else begin Result := True; end; end; {--检测是否需要安装Probe配置文件--} function NeedInstallProbeConfig(): Boolean; begin if FileExists(ExpandConstant('{app}') + '\Prober\probe.conf') then begin Result := False; end else begin Result := True; end; end; {--检检测是否已经IE8--} function CheckHaveIE8(): Boolean; var ResultStr: String; ResultCode: Integer; begin RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Internet Explorer', 'Version', ResultStr); if ResultStr = '8.0.6001.18702' then begin result := False; end else begin result := True; end; end; {--启动服务前删除多余数据--} procedure BeforeInstallDelete(); var whileLen: Integer; begin whileLen := 0; while whileLen <> 5 do begin if(FileExists(ExpandConstant('{app}') + '\Prober\probe.db')) then begin DeleteFile(ExpandConstant('{app}'+ '\Prober\probe.db')); whileLen:= whileLen+1; end else begin whileLen := 5; end; end; if(FileExists(ExpandConstant('{app}') + '\Prober\probe.db')) then begin MsgBox('文件“\Prober\probe.db”清理失败!',mbError, MB_OK); end; DelTree(ExpandConstant('{app}'+ '\Prober\log'), True, True, True); DelTree(ExpandConstant('{app}'+ '\Prober\mq_ext'), True, True, True); end; {--开始前检测--} function InitializeSetup(): boolean; var ResultStr: String; ResultCode: Integer; whileLen: Integer; begin CheckHaveIE8; //是否已经安装本软件 whileLen := 0; while whileLen <> 3 do begin if(CheckHaveApp) then begin result:=true; whileLen := 3; end else begin result:=false; whileLen:= whileLen+1; end; end; //是否需要组建 if(result) then begin if (NeedInstallDotNet) then begin MsgBox('您的电脑需要先安装Microsoft .NET Framework 2.0 SP2组建.' + #13 + '请等待组建加载完成并完成组建安装后再进行程序的安装.',mbError, MB_OK); ExtractTemporaryFile('{#MyFormationDotNetName}'); Exec(ExpandConstant('{tmp}\{#MyFormationDotNetName}'), '', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode); end; if (NeedInstallDotNet) then begin MsgBox('您的组建安装失败,程序将退出安装.',mbError, MB_OK); Result :=false; //安装程序退出 end else begin Result :=true; //安装程序继续 end; end; end; {-- 创建插件页面 --} procedure CreateTheWizardPages; var Page: TWizardPage; Button, FormButton: TNewButton; Panel: TPanel; HaveIE8Bool: Boolean; begin Page := CreateCustomPage(wpWelcome, '插件安装', '请选择您需要安装的插件'); HaveIE8Bool := CheckHaveIE8; CB_IE := TNewCheckBox.Create(Page); CB_IE.Top := ScaleY(35); CB_IE.Left := ScaleY(40); CB_IE.Width := Page.SurfaceWidth div 2; CB_IE.Height := ScaleY(17); CB_IE.Caption := '安装IE8插件'; CB_IE.Checked := HaveIE8Bool; CB_IE.Enabled := HaveIE8Bool; CB_IE.Parent := Page.Surface; CB_Flash := TNewCheckBox.Create(Page); CB_Flash.Top := CB_IE.Top + CB_IE.Height + ScaleY(8); CB_Flash.Left := ScaleY(40); CB_Flash.Width := Page.SurfaceWidth div 2; CB_Flash.Height := ScaleY(17); CB_Flash.Caption := '安装Flashplayer11插件'; CB_Flash.Checked := True; CB_Flash.Parent := Page.Surface; end; {--- 页面初始化 --} procedure InitializeWizard; begin {-- 创建插件页 --} CreateTheWizardPages; {-- 创建配置页 --} UserPage := CreateInputQueryPage(wpReady, '配置', '请进行如下配置,然后进入下一步', '请确保填写正确的信息'); UserPage.Add('服务端IP', False); UserPage.Add('监测点ID', False); ConfigBool := True; end; {-- 下一步按钮事件响应 --} function NextButtonClick(CurPageID: Integer): Boolean; begin Result := True; if CurPageID = UserPage.ID then begin if UserPage.Values[0] = '' then begin MsgBox('请填写服务端IP', mbError, MB_OK); Result := False; end else if UserPage.Values[1] = '' then begin MsgBox('请填写监测点ID', mbError, MB_OK); Result := False; end; end; if CurPageID = wpReady then begin if FileExists(ExpandConstant('{app}') + '\Prober\network.conf') and FileExists(ExpandConstant('{app}') + '\Prober\probe.conf') then begin ConfigBool := False; end; end; end; {-- 页面跳转时 实现是否允许跳转 --} function ShouldSkipPage(PageID: Integer): Boolean; begin Result := False; if PageID = UserPage.ID then begin if ConfigBool = False then begin Result := True; end; end; end; {-- 去字符串空格 --} function StringTrim(a: string): string; begin Result := a; while pos(' ',Result)<>0 do delete(Result,pos(' ',Result),1); end; {-- 方法: 实现对配置文件拷贝后进行处理 --} procedure MyAfterInstall(); var XMLDoc0: Variant; XMLDoc1: Variant; s: string; begin if ConfigBool then begin try XMLDoc0 := CreateOleObject('MSXML2.DOMDocument'); XMLDoc0.async := False; XMLDoc0.resolveExternals := False; XMLDoc0.load(ExpandConstant('{app}') + '\Prober\network.conf'); XMLDoc0.selectSingleNode('//channel[@name=''balance'']').attributes.getNamedItem('peer_addr').text := StringTrim(UserPage.Values[0]); XMLDoc0.save(ExpandConstant('{app}') + '\Prober\network.conf'); except RaiseException('未能正确配置服务端IP,请检查network.conf'); end; try XMLDoc1 := CreateOleObject('MSXML2.DOMDocument'); XMLDoc1.async := False; XMLDoc1.resolveExternals := False; XMLDoc1.load(ExpandConstant('{app}') + '\Prober\probe.conf'); XMLDoc1.selectSingleNode('//mid').text := StringTrim(UserPage.Values[1]); XMLDoc1.save(ExpandConstant('{app}') + '\Prober\probe.conf'); except RaiseException('未能正确配置监测点ID,请检查probe.conf'); end; end; end; {-- 卸载程序时对用户是否保留插件 --} procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); var XMLDoc0: Variant; XMLDoc1: Variant; begin //进入卸载后改变状态 IsUninstallRuned := true; if CurUninstallStep = usUninstall then begin if MsgBox('是否需要保留配置文件?', mbConfirmation, MB_YESNO) = IDYES then begin IsSaveConfig := True; try XMLDoc0 := CreateOleObject('MSXML2.DOMDocument'); XMLDoc0.async := False; XMLDoc0.resolveExternals := False; XMLDoc0.load(ExpandConstant('{app}') + '\Prober\network.conf'); XMLDoc0.save(ExpandConstant('{app}') + '\Prober\network_tmp.conf'); XMLDoc1 := CreateOleObject('MSXML2.DOMDocument'); XMLDoc1.async := False; XMLDoc1.resolveExternals := False; XMLDoc1.load(ExpandConstant('{app}') + '\Prober\probe.conf'); XMLDoc1.save(ExpandConstant('{app}') + '\Prober\probe_tmp.conf'); except end; end else begin IsSaveConfig := False; end; end; end; {-- 删除后操作 对文件进行一定的处理 --} procedure DeinitializeUninstall(); var XMLDoc0: Variant; XMLDoc1: Variant; begin //首先判断是否进入了卸载 if IsUninstallRuned then begin if IsSaveConfig then begin try DeleteFile(ExpandConstant('{app}'+ '\Prober\probe.db')); DelTree(ExpandConstant('{app}'+ '\Prober\log'), True, True, True); DelTree(ExpandConstant('{app}'+ '\Prober\mq_ext'), True, True, True); DelTree(ExpandConstant('{app}'+ '\Prober_Update'), True, True, True); DelTree(ExpandConstant('{app}'+ '\Prober_Watchdog'), True, True, True); except MsgBox('清空程序日志及数据库缓存失败!', mbInformation, MB_OK); end; try XMLDoc0 := CreateOleObject('MSXML2.DOMDocument'); XMLDoc0.async := False; XMLDoc0.resolveExternals := False; XMLDoc0.load(ExpandConstant('{app}') + '\Prober\network_tmp.conf'); XMLDoc0.save(ExpandConstant('{app}') + '\Prober\network.conf'); XMLDoc1 := CreateOleObject('MSXML2.DOMDocument'); XMLDoc1.async := False; XMLDoc1.resolveExternals := False; XMLDoc1.load(ExpandConstant('{app}') + '\Prober\probe_tmp.conf'); XMLDoc1.save(ExpandConstant('{app}') + '\Prober\probe.conf'); except MsgBox('保留配置文件失败!', mbInformation, MB_OK); end; try DeleteFile(ExpandConstant('{app}'+ '\Prober\network_tmp.conf')); DeleteFile(ExpandConstant('{app}'+ '\Prober\probe_tmp.conf')); except MsgBox('清空配置文件缓存失败!', mbInformation, MB_OK); end; end else begin DelTree(ExpandConstant('{app}'), True, True, True); end; end; end;