Keywords 关键字 InstallShield, Uninstallation Application, Creating Uninstallation Shortcut, 卸载,创建卸载快捷方式, XiaoZhu.com, piggybank
[说明] 本文由 piggybank 花费了一定的心血编写,所以转载或引用时务必注明来源,保证本说明及原文完整性。
如果需要在报刊转载,请与我联系
,谢谢!
原文刊载在: http://blog.xiaozhu.com/play/
下文中将分别就使用 InstallShield 提供的功能及使用 InstallScript 脚本创建卸载快捷方式进行说明:
- 不用脚本创建快捷方式
- 使用用脚本创建卸载快捷方式的方法
- 常用的卸载方法
- 创建卸载快捷方式的补充说明
不用脚本创建卸载快捷方式
记得大概是 InstallShield 7 开始提供了多种操作环境。在 Project Assistant 方式下,使用者可以跟着 Wizard, Step by Step 地创建自己的 Project。这一点,很像 InstallShield 的另外一个产品: InstallShield Express ^oo^
在 InstallShield Professional 7 以后的版本中,可以把视图切换到“Project Assistant”方式,在第 五步:“Application Shortcuts”的左边你可以看到“More Options”(我这里以 ISX 版本为准)这个 Pannel,马上看到“Create an uninstallation shortcut”——毫不犹豫地按下去 wow, my god, it's a miracle ! (不好意思,刚刚又看了一遍《Shawn Shank's Redemption》)
在各个版本的使用过程中发现:在这一步,无论是创建卸载快捷方式,还是创建其它的快捷方式,很容易导致 IS 崩溃。我一般是切换到 Installation Designer 视图进行操作。
IS X 似乎是最稳定的一个版本了(也许仅仅是对我而言)。可当我在创建完快捷方式之后为了抓下面这幅图,自己点了一次这个按钮,IS 就崩溃并重新启动了。本来以为也许与我的本地环境有些关系,但后来一位朋友因为重来没有一次“侥幸逃脱”过,而不得不采用脚本方式创建卸载快捷方式。呵呵,看来我还是比较幸运地 ^oo^

使用用脚本创建卸载快捷方式的方法
我们先看看官方是怎么推荐的:
prototype CreateUninstallShortcut();
function CreateUninstallShortcut()
string strCmdLine;
LIST lstPath;
begin
// For an InstallScript installation:
strCmdLine = DISK1TARGET ^ 'Setup.exe';
// For an InstallScript MSI installation:
strCmdLine = UNINSTALL_STRING;
// The path has to be handled differently if you are running
// an InstallScript MSI installation on Windows 9X.
if ( SYSINFO.WIN9X.bWin9X ) then
lstPath = ListCreate( STRINGLIST );
StrGetTokens( lstPath, UNINSTALL_STRING, '/' );
ListGetFirstString( lstPath, strCmdLine );
LongPathToQuote( strCmdLine, TRUE );
strCmdLine = strCmdLine + ' /M' + PRODUCT_GUID;
endif;
// Create the shortcut.
AddFolderIcon(FOLDER_PROGRAMS ^ 'Uninstall Shortcut', 'Run the Uninstall',strCmdLine, '','',0, '', NULL );
end;
InstallShield 各个版本中存在一点点细微的差异。因为我无法安装以前的版本来验证,所以没能在这里对比每一个版本的情况。但记得当初把 InstallShield Professional 7 制作的安装程序 Project 升级到 InstallShield Developer 8.02 版本之后,我在 InstallScript 中创建的卸载快捷方式就有问题了。
在那个类型为 'InstallShield MSI Project' 的项目中,创建卸载时使用的是 UNINSTALL_STRING 中提供的值。仔细跟踪检查发现,正是这个 UNINSTALL_STRING 在新的版本中其引号的封闭位置不对,造成在 LaunchAppAndWait 中使用的时候,对于长文件路径的引号封闭不正确,于是无法正常使用(跟踪调试时把其值复制出来在“运行”执行,或查看创建的快捷方式的属性:“目标”)。
当时写了一段代码处理这一情况,可惜手边没有保留。于是(搜索 CSDN )找到了当时回复别人的帖子时写的一段处理代码:
szUninstall = UNINSTALL_STRING;
nResult = StrFind(szUninstall, '.exe');
if ( ( StrFind(szUninstall, '\'') < 0 ) && ( nResult >= 0 ) ) then
StrSub(szTemp1, szUninstall, 0, nResult + 4);
StrSub(szTemp2, szUninstall, nResult + 4, 200);
szUninstall = '\'' + szTemp1 + '\'' + szTemp2;
UNINSTALL_STRING = szUninstall;
endif
可以看出来作用与官方代码针对 SYSINFO.WIN9X.bWin9X 处理的这一段相同。而我是在 WinXP 和 Win2K 的计算机上发现这一问题的。那么,也就是说在 IS8 版本中的脚本可以去掉这一判断,从而不必区分操作系统版本地修正 UNINSTALL_STRING 的值(我没测试过效果,还请自行测试)。
而 InstallShield DevStudio 9 以及现在的 InstallShield X Premier 版本中不再存在这个问题。回忆当初使用 InstallShield Professional 7.0 版本时也没有问题。看来,也许只有 InstallShield Developer 8 版本中存在这样的问题吧。 当然,也许 InstallShield Developer 8 版本的某个 Service Pack 或者 Hotfix 解决了这个问题也说不定,在这里不过是提醒一下,没有遇到这样的问题最好 ^oo^
常用的卸载方法
除了创建卸载快捷方式,在调试的过程中我们可能还需要在没有卸载快捷方式的情况下卸载一个软件。可以使用下面的几种方法:
(根据例子可以自行改为创建快捷方式的方法,当前项目的 Product Code 可以用预定义变量 Produce_GUID 来代替。但本文末尾会说明为何推荐使用 UNINSTALL_STRING)
1、借助 Windows Installer 自带的 MSIExec.exe
查阅 Help,有关 msiexec.exe 的 commandline 参数即可知道:
| /x or |
The /x option uninstalls a product. |
在脚本实现的时候,如果是 Basic MSI 或者 InstallScript MSI 项目,可以用 Windows Installer 提供的 msiexe.exe 来进行安装和卸载。
比如在你的安装过程中如果需要安装另外一个 msi,就是调用 msiexec.exe 来进行的,如命令:
msiexec.exe /i c:\temp\mdac.msi
用 InstallScript 实现:
LaunchAppAndWait(SystemFolder ^ 'msiexec.exe', '/i' + TARGETDIR ^ 'mdac.msi', WAIT);
用 msiexec 来卸载的命令是(斜体字部分换成需要卸载的软件的 Product Code):
msiexec.exe /x {D6621CB2-4464-4608-922E-B6E7BDCA9760}
换成用 InstallScript 实现(斜体字部分换成需要卸载的软件的 Product Code):
LaunchAppAndWait(SystemFolder ^ 'msiexec.exe', '/x {要卸载的产品的 Product Code}', WAIT);
2、借助 InstallShield 提供的 IDriver.exe
[CommonFilesFolder]InstallShield\Driver\10\Intel 32\IDriver.exe /M{要卸载的产品的 Product Code}
在目标计算机上等同于:
'%SystemDrive%\Program Files\Common Files\InstallShield\Driver\10\Intel 32\IDriver.exe' /M{要卸载的产品的 Product Code}
或:
'%CommonProgramFiles%\InstallShield\Driver\10\Intel 32\IDriver.exe' /M{要卸载的产品的 Product Code}
用 InstallScript 实现:
LaunchAppAndWait(CommonFilesFolder ^ 'InstallShield\Driver\10\Intel 32\IDriver.exe', '/M{要卸载的产品的 Product Code}', WAIT);
或:
LaunchAppAndWait('%SystemDrive%\Program Files\Common Files\InstallShield\Driver\10\Intel 32\IDriver.exe', '/M{要卸载的产品的 Product Code}', WAIT);
呵呵,其实如果输出 UNINSTALL_STRING,你会发现这就是它的内容。
安静模式的卸载:
[CommonFilesFolder]InstallShield\Driver\10\Intel 32\IDriver.exe /M{要卸载的产品的 Product Code} /uninst
参考上文的 InstallScript 写法:
LaunchAppAndWait(CommonFilesFolder ^ 'InstallShield\Driver\10\Intel 32\IDriver.exe', '/M{要卸载的产品的 Product Code} /uninst', WAIT);
要注意,安静模式下不会执行 InstallScript 脚本,系统会回滚到安装之前的样子。就好比使用 CleanSweap 一类的软件监视系统,对比一个软件安装前后的变化,最后通过复原的方式来“卸载”软件一样。
(并注意控制面板中“添加删除程序”提供的“删除”按钮就是安静模式卸载。在《[InstallShield] 卸载相关问题》一文中会讨论安静模式对我们的影响。)
3、借助 Setup.exe 的卸载参数
对于 InstallShield 生成的 Setup.exe,可以使用 /uninst 参数来调用它,此时就不是安装,而是卸载了:
Setup.exe /uninst
调试的时候,这是最简单的卸载已有产品的方法(尤其遇到“升级”的时候出现的一些问题)。
同样,Setup.exe 也提供安静模式的卸载。首先用下面的命令产生一个应答文件:
Setup.exe /r
然后执行下面的命令:
IDriver.exe /M{要卸载的产品的 Product Code} /s /f1“\上一步生成的应答文件.iss”
4、InstallShield 为方便调试提供的功能

估计这一菜单项所采用的方法就是上一节介绍的 Setup.exe /uninst
创建卸载快捷方式的补充说明
官方推荐的在 IDE 中创建卸载快捷方式的方法如下:
To create an uninstallation shortcut via the IDE:
- Open the Shortcuts view.
- Create a shortcut with the following properties to launch IDriver.exe:
| Shortcut Property |
Value (InstallScript project) |
Value (InstallScript MSI project) |
| Arguments |
(None) |
/M{Product Code} |
| Target |
\Setup.exe |
[CommonFilesFolder]InstallShield\Driver\7\Intel 32\IDriver.exe |
In the above example, {Product Code} would be replaced with your product code. It might look similar to the following:
Arguments: /M{7C071035-F334-11D5-818A-00C04F288311}
本来,按照前面说的方法,无论是否使用脚本已经可以创建快捷方式了,看这里还有什么必要呢?
因为我从来没有使用过〈不用脚本创建卸载快捷方式〉的方法创建卸载快捷方式,一直都是使用脚本和 UNSINTALL_STRING,所以也觉得无所谓。但在一次帮助一位朋友的过程中自己实际体验了才发现,官方的推荐是有意义的。具体原因请参考:《[InstallShield] 卸载相关问题》一文。
所以,如果你的安装程序是 'InstallScript MSI Project' 类型,对于前面在图形界面中创建的快捷方式,最好还是调整一下。切换到“Installation Designer”视图,将:

中划红线部分改为:

《[InstallShield] 卸载相关问题》一文中已经讨论了相关问题,这里就不罗嗦了。至于脚本方式创建的卸载快捷方式,对于 Basic MSI Project 推荐使用 MSIEXEC.exe 来卸载。其它类型的安装程序,使用预定义变量 UNINSTALL_STRING 是最好的方法(注意检查 IS8 的问题),因为它与上图中一样都是调用 IDriver.exe 来完成卸载。
呵呵,再次提醒一点,Basic MSI Project 和 InstallScript MSI Project,以及 Merge Module Project 中可以使用 INSTALLDIR 这个预定义的变量,而在 InstallScript Project 中,却要换成 TARGET 才行,否则编译的时候就会出现 C8025 的错误 ^oo^