有关 InnoSetup 软件打包的技术细节处理
【文 / 张赐荣】
InnoSetup是我最喜欢的一款软件封装工具,其可扩展性能满足各类程序的安装部署需要,脚本的[Code]段更是强大到没朋友,众所周知咱们的ZDSR便是用他打包而成,(虽然安装简单,但实现起来也不是用向导就能完成的,加上要考虑到目的计算机的多样性,所以ZDSR的安装包还真值得我们研究学习一下),但今天我可不是来分享研究成果的。
为什么标题写为“细节处理”呢?因为这的确是个细节问题,细节到多数开发者都视而不见。
即便如此,作为有知识、有思想、有节操的社会主义五好青年,我们岂能泯然众人,哈哈哈!古人云“祸患常积于忽微”吗!
细节1: 检测是否已安装。
目前常用的方法有:
(1)检测安装程序目录,以及主程序是否存在。
(2) 检测进城是否正处于运行状态。
(3) 检测注册表内的APPID。
我采用的是第(3)种,当检测到APPID与当前安装包相同时便弹出对话框提醒,并执行卸载程序,感觉相对保险些,但也有比较坑的时候,假如用户位正确卸载我们的程序,(也就是存在注册表残留),那可就坑了你除非手动去删除注册表内的相关键值才能重新安装新版程序,但这种情况一般是有意而为之,怨天怨地怨不了我,哈哈哈!
细节2: 卸载前关闭程序
常规方法与细节1十分相似,无非是判断进城是否正在运行,从而kill掉,或者弹出对话框提醒用户手动关闭,不再赘述。
另外,可能有朋友知道一种更高大上且保险的方法:添加互斥对象,InnoSetup中也有相关参数,下面摘抄一段Inno的帮助文档:
##分割线开始##
描述:
这个指令用于防止用户在应用程序仍在运行的情况下安装新的应用程序版本,以及防止用户卸载正在运行的应用程序。它指定一个或多个已命名互斥中的名字 (多重互斥用逗号隔开),安装程序和卸载程序在启动时检查该名字。如果没有退出,安装程序/卸载程序将显示消息: “[安装程序或卸载程序] 发现 [AppName] 当前正在运行,请现在关闭所有运行中的程序,请先关闭所有运行的窗口,然后单击“确定”继续,或按“取消”退出。”。这个值可以包含常量。
使用这个指令需要你添加代码到你的应用程序,这个应用程序是用你在这个指令中指定的名字创建一个互斥的应用程序。
##分割线结束##
这些方法不能说好坏,只能说适合与否,也许有些老鸟编写[code]游刃有余,但有些新手却望而生畏!下面再给大家说说我的方法,上面提到了,我利用读取注册表内APPID的方法来判断是否重复安装,那么卸载的时候我是如何处理的呢?
方法很简单,那便是通过传入命令行参数,使程序自己退出,大致步骤如下:
1. 在我自己的程序启动时取得命令行参数。
2. 检测是否正确,比如我定义的是“-Uninstall”。
3. 假如参数没有问题,那么判断我的程序是否正在运行,如果返回 True,则关闭,或提示用户手动关闭(通常没有必要)。
4. 在InnoSetup安装包脚本内的[UninstallRun]段添加一行: Filename: {app}{#MyAppExeName} ; Parameters: -Uninstall
5. 大功告成,代码也不会很多,与互斥对象有异曲同工之妙,但更为简单,当然不是万无一失,笔者只是一时兴起将自己所学记录下来,希望能起到抛砖引玉的作用,关于Inno的更多知识,欢迎一起交流。
##自己常用红的代码收藏##
此代码功能包括:去掉欢迎页面,退出安装向导时不提示,去掉菜单内的“关于按钮”,不重复安装(提示卸载旧版程序),关于不重复安装我之前写过一篇文章,在我的博客内也能找到。
[Code]
//去掉欢迎页面(代码开始)
function ShouldSkipPage(PageID: Integer): Boolean;
begin
if PageID=wpWelcome then
result := true;
end;
//去掉欢迎页面(代码结束)
//退出安装向导时不提示(代码开始)
procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
begin
Confirm := False;
end;
//退出安装向导时不提示(代码结束)
//去掉菜单内的“关于按钮”(代码开始)
procedure InitializeWizard();
begin
WizardForm.BorderIcons := [biHelp, biSystemMenu, biMinimize]; //与BorderStyle合用,会导致许可协议等页面的RTF文本失效
end;
//去掉菜单内的“关于按钮”(代码结束)
//不重复安装(代码开始)
function InitializeSetup():boolean;
var
MykeynotExist:boolean;
ResultCode: Integer;
uicmd: String;
begin
MykeynotExist:= true;
if RegQueryStringValue(HKEY_LOCAL_MACHINE, ‘SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall{此处为APPID}_is1’, ‘UninstallString’, uicmd) then
begin
MsgBox(‘检测到程序已安装,请卸载后在运行此安装向导!’, mbInformation, MB_OK );
MyKeynotExist:= false;
Exec(RemoveQuotes(uicmd), ”, ”, SW_SHOW, ewWaitUntilTerminated, ResultCode);
end;
Result:= MykeynotExist
end;
//不重复安装(代码结束)