[InstallShield] 卸载相关问题

说明] 本文由 piggybank 花费了一定的心血编写,所以转载或引用时务必注明来源,保证本说明及原文完整性。

如果需要在报刊转载,请与我联系 ,谢谢!

原文刊载在: http://blog.xiaozhu.com/play/

--------------------------------------------------------------------------------

在后面的内容中,主要解答以下几个经常有朋友问到,却又往往得不到很好的解决的问题:

如何创建卸载快捷方式?
为什么卸载的时候不执行 OnMaintUIBefore 和 OnMaintUIAfter?
为什么卸载的时候不执行 OnUnInstall?
为什么卸载的时候并没有调用 OnMaintUIBeforeXXXX 或者 OnUnInstall,甚至连 OnBegin、OnAppSearch、OnShowUI 等等事件处理函数都没有调用?
为什么第二次运行安装程序的时候毫无提示就卸载了以前的版本并没有调用 OnMaintUIBeforeXXXX 或者 OnUnInstall?

--------------------------------------------------------------------------------

关于如何创建卸载快捷方式的问题,请参考:〈InstallShield: Creating Uninstallation Shortcut 创建卸载快捷方式〉一文

请记住那个表格。在脚本中创建卸载快捷方式最好的方法就是用用于定义常量 UNINSTALL_STRING 提供的值。而在 IS操作界面中创建卸载快捷方式最好参考帮助中(参考该文)表格的方法,根据不同的项目类型采用不同的方法。如果用 IS提供的方便功能创建的卸载快捷方式有些毛病,最好改改——至于原因,在后面会提到。

--------------------------------------------------------------------------------

为什么卸载的时候不执行 OnMaintUIBefore 和 OnMaintUIAfter?
为什么卸载的时候不执行 OnUnInstall ?
在General Information -> Project Properties 你能看到:Enable Maintenance这一选项。如果设置为 Yes,那么当用户在一台已经安装了该软件的计算机上再次运行安装程序,则会自动运行 OnMaintUIBefore 和OnMaintUIAfter 事件处理函数中的脚本。如果设置为 No,那就会调用 UnInstall 事件处理函数的脚本。

那么,如果卸载的时候不执行这两个事件处理函数的脚本,就要检查一下这一设置了。

但(呵呵,这里有个“但”),卸载的时候也可能不运行这两个函数以及 OnUnInstall,耐心看下去吧。

--------------------------------------------------------------------------------

为什么卸载的时候并没有调用 OnMaintUIBeforeXXXX 或者 OnUnInstall,甚至连 OnBegin、OnAppSearch、OnShowUI 等等事件处理函数都没有调用?
1、安装程序如果运行在“安静”模式下,则不会执行这些事件处理脚本。

比如 setup.exe /s 或者 IDriver.exe /M{Product Code} /uninst 这样的调用(请参考:〈InstallShield: Creating Uninstallation Shortcut 创建卸载快捷方式〉一文)。

2、如果不是在“安静模式”,用户在控制面板的 添加删除程序 中,直接点了列在程序项后面的“删除”而不是“更改”,则会运行在 REMOVEONLY 模式下。此时不出现维护界面,但并不是没有执行相应脚本。

假如 Enable Maintenance 的设置为 Yes,按照上面的说法,显然应该执行 OnMaintUIBefore 事件处理函数的脚本,但因为其默认代码如图:


所以不会调用 SdWelcomeMaint ,也就不会出现维护界面。所以容易错以为 OnMaintUIBefore 没有效果。
我们来看看“添加删除程序”的按钮和设置的关系:

其设置结果如图:



3、不同的方法创建的卸载快捷方式也可能导致卸载过程不执行任何脚本。

最近一次为 xzSQLDeploy 制作安装程序(请参考〈InstallShield Example: 演示 xzSQLDeploy 和xzIISConfig 脚本的使用〉一文提供的 InstallShield X 制作的范例),我采用了 IS提供的快捷功能来创建卸载快捷方式:在 Project Assistant 方式下的 Application Shortcuts这一步执行左边的 Create an Unstallation Shortcut(请参考〈InstallShield: CreatingUninstallation Shortcut 创建卸载快捷方式〉一文) :
结果对比发现该快捷方式采用的是 MSIExec.exe 的 /x 参数来进行卸载——于是卸载不是运行在 IS 下,没有调用 IS 的事件处理函数的脚本。

所以,如果使用 IS 提供的快捷功能创建快捷方式,记着检查其 Target。如果需要在卸载的时候执行一些特别的动作(比如在你的脚本删除某些文件、删除创建的 IIS 站点等等),那就改为(这里的“7”根据对应的IS版本改为8、9、10):

(请参考〈InstallShield: Creating Uninstallation Shortcut 创建卸载快捷方式〉一文)

[CommonFilesFolder]InstallShield/Driver/7/Intel 32/IDriver.exe

连同参数,在目标计算机上就等同于

"%SystemDrive%/Program Files/Common Files/InstallShield/Driver/10/Intel 32/IDriver.exe" /M{你的产品的 Product Code}
如果你按照上面说的方法采用 UNINSTALL_STRING,并调试输出其值,你会发现它就是上面的内容 ^oo^

 

--------------------------------------------------------------------------------

为什么第二次运行安装程序的时候毫无提示就卸载了以前的版本并没有调用 OnMaintUIBeforeXXXX 或者 OnUnInstall?
注意下图:


在 Tools 菜单中选择 Options,在弹出窗口的 Preferences 这一页去掉对 "Uninstall before installing" 的选中,重新编译并运行。

如果 Enable Maintenance 的设置为 Yes,执行 Setup.exe 完成安装,然后再次执行 Setup.exe 就会出现下图所示的维护界面:


如果 Enable Maintenance 的设置为 No,则执行 OnUninstall 事件处理函数的脚本。如果不想出现那个讨厌的提示框,那你爱怎么改就怎么改了 ^oo^

Feedback
# XiaoZhu.com: [InstallShield] 卸载相关问题 2004-10-24 12:35 piggybank
Ping Back来自:blog.csdn.net

# re: [InstallShield] 卸载相关问题 2004-10-27 10:19 pk
piggybank,请教两个问题。
1.用installshield X,能在脚本里远程调用另外一台机器里的可执行程序吗?我用LaunchAppAndWait()试过,不行。
2.安装程序如何要实现以下功能:先往被安装机器里拷贝一些文件,修改注册表,重新启动机器,然后执行先前刚拷到机器里的一个可执行程序。
谢谢!

# re: [InstallShield] 卸载相关问题 2004-10-27 11:07 piggybank
pk,不用客气

1、InstallShield 中涉及到 LaunchAppAndWait 等不支持网络资源访问。但是可以测试一下先把网络资源映射为本地硬盘,应该是可以的。

2、启动时运行,一般都是在注册表的 Run、RunOnce 或者启动组方一个快捷方式来实现的。
比如:
HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/Run
HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/RunOnce
HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/RunOnceEx
HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/RunServices
HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/RunServicesOnce

InstallShield 自己也支持安装过程中中途重新启动,下次继续。
HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/RunOnce
HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/RunOnceEx
HKEY_LOCAL_MACHINE/System/CurrentControlSet/Session Manager/FileRenameOperations
比如 IS 会监视在安装过程中上述注册表位置下的项是否发生变化,如果发生变化表明需要重新启动。
当然,在你的需求里只要把你要运行的程序的快捷方式放到快捷组里就足够了。

# re: [InstallShield] 卸载相关问题 2004-10-28 10:48 pk
piggybank,谢谢你的答复!

怪我自己,昨天没把情况讲清楚。

其实我现在遇到的问题是:
刚刚完成了一个JSP作的信息管理系统,B/S的。数据库用的是ORACLE9i,OS是windows2000server,我本来按照以往的方法作好了一个在数据库服务器本地执行的数据库安装和初始化程序SRVINST,包括创建用户、建表等等。是由批处理命令和SQL文件组成的,功能和你提供的xzSQLDeploy类似(我的没有GUI界面,难看些,呵呵)。现在项目要验收了,用户忽然要求作一个所谓的数据库远程安装程序,就是说在任何一台联网的机器上(可能没有安装ORACLE客户端),只要运行安装程序,就能对指定的数据库服务器进行数据库的安装和初始化,当然前提是服务器端的ORACLE实例已经建好,并且监听和实例等服务都启动了。

我原本考虑了两个解决的方法:
第一就是看能否在InstallShield里能否远程访问?如果行,就直接调用服务器上的SQLPLUS执行本地的SRVINST。也就是我昨天问你的问题1。不过看来好像不行呀,我不能要求用户在安装前先将服务器网络资源映射为本地硬盘呀。领导那儿也通不过的。

第二就是干脆将ORACLE的客户端打包到安装程序里(虽然有点版权问题,好在服务器端的ORACLE是用户掏钱了的,将就点了)。
具体是:
1.将打包的ORACLE 9i的客户端文件和数据库创建及初始化程序SRVINST(install.bat与SQL文件)拷贝到执行安装程序的本地机器上。
2.显示一对话框,让用户输入远程的ORACLE 服务器的机器名。
3.修改本地ORACLE 9i的客户端中$ORACLE_HOME/network/admin/tnsnames.ora文件, 将“HOST = pk”改为“HOST = 用户输入的ORACLE 服务器的机器名”。
4.导入有关ORACLE 9i的客户端的注册表。
5.重新启动机器。
6..在脚本里通过LaunchAppAndWait()函数本地调用install.bat文件,远程创建数据库及初始化。

在安装过程中重新启动机器然后继续剩余的安装过程,对于这一点我一直没能解决,也就是我昨天跟你请教的问题2了。

呵呵,罗嗦了半天,不知道讲清楚了没。主要是我觉得你讲的在注册表里进行处理来解决重新启动的方法对我好像不适用,同时也是想听听你的意见,看看我这么处理好不好。

对了,昨天在CSDN上查到一篇有你的回复的帖子:http://search.csdn.net/Expert/topic/2105/2105147.xml?temp=.7887689
你那个处理方法好像适合我,但是我试了试,没成功。可能是哪个地方用得不对,我刚刚用INSTALLSHIELD X,很多地方不清楚,能否请你说得详细点。我的MSN是:[email protected],能否加我?

说句题外话,你文章里的图片是用什么软件处理的,蛮漂亮呀,想学学。

# re: [InstallShield] 卸载相关问题 2004-10-28 11:10 piggybank
对于 网络映射,其实可以用 cmd shell 提供的 net.exe 实现: net use ...(用 net help use 察看详细信息)。当然,这个方法并不好。
你说的在目标计算机上安装客户端是一个办法。事实上,该计算机如果有需要对远端的数据库服务器进行操作,那就表明该计算机被用作管理计算机。所以,安装 Oracle 客户端在逻辑上是很正确的。
还有一个替代办法就是采用 java 写一段程序去设置远端数据库服务器,然后编译为 exe,采用 JDBC适当的驱动,就不必依赖客户端支持了。但同样地要部署 J2SE/J2SD 和 JDBC 驱动,也一样麻烦,呵呵。(这一点倒是提醒我可以继xzSQLDeploy 之后做一个 java 版本支持 oracle/mysql)

对于 Web 应用的部署,我一直认为在安装过程中进行 WebServer/DBServer 配置并不是一个好办法。也就是说这与安装本身在逻辑上是不同的两件事情。
其实看你列出来的步骤,运行 Install.bat 其实已经是安装完毕之后的事情了。逻辑上也和上面的观点一致。那么,就与那个帖子中提到的“重启之后继续安装”有所区别。
因此,重点解决“如何重启”,或者“如何提示用户重启”的问题即可。
对于重新启动,上面的回复中已经提到 IS 在安装过程中如果发现启动组或者那些注册表项内容变化就会在结束安装时提示用户重新启动。如果要强制重新启动或者明确地提示用户需要重新启动,就要在脚本中改一改。
比如采用 sdFinishReboot 或者 RebootDialog 对话框(麻烦看一下帮助,最近比较忙)。系统重新启动后执行你的批处理,就 OK 了。

呵呵,至于图片嘛...

是用 SnagIt 7.x 抓图,并用它的图片处理功能处理的,值得推荐 ^oo^

# re: [InstallShield] 卸载相关问题 2004-10-28 11:16 piggybank
对了,记得 System 可以重新启动系统,补充查了一下参数:
分别试试看:
System(SYS_BOOTMACHINE);
System(SYS_BOOTWIN);
以前版本的 help 中见过这个用法,但在 ISX 的帮助中关联的文档似乎不正确,所以找不到具体的地址,没记错的话应该是上面两个命令也可以让系统重启——而不提示用户。
当然,当前用户要有足够权限才行。

# re: [InstallShield] 卸载相关问题 2004-10-28 11:22 piggybank
嗯,确定了。
ISX 推荐 sdFinishReboot 或者 RebootDialog ,而 System(SYS_BOOTMACHINE) 只是为了兼容过去的 Professional 版本而设置。
前者有对话框提示用户,比较友好一些。后者直接就试图重新启动了。

# re: [InstallShield] 卸载相关问题 2004-10-28 11:33 pk
哈哈,你的回帖可真快呀。
谢谢了,马上试试!

# re: [InstallShield] 卸载相关问题 2004-11-10 16:51 fangzq
请教一下:安装在系统目录下的文件在卸载的时候怎么删除掉?Component中有个选项Permanent的说明中说SystemFolder下的文件都不删除的,有什么方法解决吗?谢谢

# re: [InstallShield] 卸载相关问题 2004-12-1 19:28 piggybank
I had answered your questions on CSDN Forum :)

# re: [InstallShield] 卸载相关问题 2004-12-8 8:26 james
向您请教一个问题。
我在一个project里做了2个release,一个单文件,一个多文件的。
为什么编译后,多文件的程序卸载时会出现WELCOME窗口,而单文件的不会出现,Enable Maintenance 已经设置为NO,难道一个project里不能同时存在多个release吗?请您帮忙解答一下,thanks very much!

# re: [InstallShield] 卸载相关问题 2004-12-8 8:27 james
sorry,忘了说一句,我使用的installshield是9.0

# re: [InstallShield] 卸载相关问题 2004-12-8 9:11 piggybank
应该不会的,IS9 我也用了一段时间的。不同的 Release 只不过是打包方式不同罢了(比如是否包含ISScript引擎、是否压缩等等),是不是你用的卸载方式不同?比如安静卸载模式下或者用了MSIExec 的卸载。

EnableMaintenance 已经设置为NO的话,应该不会有维护界面出现——建议你还是看看 OnMaintBefore 的事件处理代码,我不确定IS9 和 ISX 具体的不同(呵呵,毕竟我没必要专门去对比一下每个版本),但 ISX 在一些细节上稍稍调整了一下,也许问题是在这里。
还有,修改了设置后是否把两个 Release 都重新编译过?测试的时候是否把原来的安装卸载了在同样的新的Release下测试的?

排除这些干扰再看看,可以肯定的是一个 Project 里不但可以存在多个 Release,还可以做多个 Patch :)

你可能感兴趣的:(Install)