最近安排我弄程序的打包工作,然后叫我接触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;