Windows Installer 故障处理
(1)问:我如何才能找出程序包安装失败的原因?
答:有三种比较好的方法可以对程序包的安装问题进行跟踪。第一种方法是通过运行校验确信您的程序包合法有效。通过进行验证,您可以发现错误和警告,并找出一些常见的安装程序制作问题。有两个工具可以对安装程序包进行验证,这两个程序都可以通过Windows Installer SDK获得:MsiVal2和Orca。MsiVal2是一个用来校验程序包的命令行工具。Orca则为验证提供了一个图形化的用户界面,并且可以突出显示程序包中的无效实体。
第二种方法是使用应用程序事件日志。Windows Installer会把成功和失败信息记录在应用程序事件日志当中。
最后一种方法是生成一个详细日志文件。然后分析该详细日志文件,并从中找出错误的根源。Windows Installer SDK提供的WILogUtl.exe工具可以帮助您分析详细日志文件。 日志记录可以通过Windows Installer日志记录策略加以启用,或者,您也可以通过在MSIExec命令行中附加'/L*v path to logfile'来启用该功能。
为了通过策略获得详尽的详细日志文件, 请使用如下注册表键:
HKLM/Software/Policies/Microsoft/Windows/Installer
设置:Logging = REG_SZ voicewarmup
设置:Debug = REG_DWORD 0x7
通过策略键生成的日志文件将以msiXXXXX.log的格式存储在用户的'%temp%'文件夹中。
注意:通过命令行产生的日志记录比所有的日志记录策略设置拥有更高的优先级。
(2)问:在我每次启动程序的时候,Windows Installer都会执行安装操作。我怎样确定产生这种按需安装的原因是什么?
答:有一种方法可以容易地确定引起按需安装的原因,那就是:在应用程序事件日志中查找以下格式的MsiInstaller日志信息:
事件类型:警告
事件来源:MsiInstaller
事件ID:1001
描述:
检测产品'{000C1109-0000-0000-C000-000000000046}',特性'Example' 在请求组件'{00030829-0000-0000-C000-000000000046}'时发生失败
事件类型:警告
事件来源:MsiInstaller
事件ID:1004
描述:
检测产品'{000C1109-0000-0000-C000-000000000046}',特性'Example',组件'{00030829-0000-0000-C000-000000000046}'失败。资源'C:/Progam Files/example/example.exe'不存在。
第一条信息(事件ID为1001)说明了哪一个组件正在被安装。此处列出的组件是在针对特殊快捷方式的Shortcut(快捷方式)表中的Component(组件)列中所指定的组件。
第二条信息(事件ID为1004)指出了哪一个组件在检测时发生失败。Windows Installer 2.0经过改进的事件日志功能已经对信息进行了更新,以便在大多数情况下,用户都可以通过事件信息查找出导致检测失败的真正问题根源。 如果组件的键路径(Keypath)丢失或者受损,可能会导致用户重新安装程序。
在上例中,用户需要重新安装程序,因为资源'c:/Program Files/example/example.exe'不存在。您应该找出导致键路径不存在的原因所在--在本例中,是因为用户删除了该文件。
(3)问:我怎样才能确定Windows Installer是否安装了我的功能特性或组件?
答:确定Windows Installer是否安装了某个特定功能或组件的方法十分简单。您可以通过Windows Installer的verbose日志文件找到答案。您首先需要查找的是InstallValidate操作的日志信息。该操作将会把程序包中每个功能和组件的安装、请求和操作状态记录下来。
MSI (s) (5C:F4): 执行操作: InstallValidate
操作开始 1:51:18: InstallValidate.
MSI (s) (5C:F4): 功能: Example; 安装: 缺席; 请求: 本地; 操作: 本地
MSI (s) (5C:F4): 组件: Example; 安装: 缺席; 请求: 本地; 操作: 本地
操作结束 1:51:18: InstallValidate. 返回值 1.
在上述日志文件片断中'Example'功能将在本地进行安装,因为它的操作状态为'本地'此外,组件'Example'也将根据给定的操作状态进行本地安装。
(4)问:为什么我的文件在卸载过程中没有被删除?
答:产生这个问题的原因主要有四种:
这些文件所属的组件被标记为'永久'(permanent)。(这一点可以通过Component表的Attributes列来实现)
这些文件所属的组件没有一个拥有组件GUID。(位于Component表的ComponentId列的该值为NULL)。Windows Installer无法管理那些没有GUID的组件。
如果组件的键路径(keypath)拥有一个共享的DLL refcount,那么该组件将不能被卸载。
如果该组件安装在系统文件夹中,而且在程序卸载之时,组件中的某一个文件拥有一个外部共享的DLL refcount,那么该组件将不能被卸载。
(5)问:为什么我的文件夹在程序卸载时没有被删除?
答:导致文件夹在程序卸载过程中不能被删除的原因主要有以下几种:
在同时使用CreateFolder表和CreateFolders操作时,执行顺序表中的RemoveFolders操作丢失。
该文件夹不是由Windows Installer创建的文件夹,因此它不会删除它们,除非您告诉Windows Installer删除这些文件夹。
文件夹中仍然存在资源。
(6)问:为什么我的注册表键在程序卸载是没有被删除?
答:导致程序卸载时注册表键没有被删除的最常见原因有以下几种:
1. Registry(注册表)表包含了带有'+'标记的实体。该符号将指示Installer在卸载程序时保留这些注册表键。
2. 在InstallExecuteSequence表中,RemoveRegistryValues操作位于UnregisterProgIdInfo和 UnregisterMIMEInfo操作之后。您需要反转这些操作的顺序。Registry表所写入的某些注册表键值会阻止特定的ProgId、扩展和CLSID 键被删除。
(7)问:为什么安装过程所占用的磁盘空间远远大于我实际安装的文件尺寸?
答:Windows Installer会计算两种类型的磁盘占用:带有回滚操作的磁盘占用;以及没有回滚操作的空间占用。没有回滚的空间占用是程序安装实际占用的磁盘空间。带有回滚操作的空间占用包括了在安装过程中为回滚操作提供支持所需的备份文件所占用的空间。此外,Windows Installer还会计算出执行安装操作所需的一些额外空间占用。其中包括安装脚本所需占用的空间以及缓存程序包的空间需求。此外,在安装期间,Installer需要对安装程序包进行临时复制。安装脚本和程序包运行副本所占用的空间是临时性的。在安装结束之后,这些文件将会被清除。请看以下示例,在本例中,您的安装程序包的大小约为80KB,而您正在安装一个4 KB的文件。(注意:根据硬盘簇大小的不同,您的数字与我的可能会有所不同):
89120字节(被缓存的MSI,基本上是4 KB簇大小的整数倍)
89120字节(MSI的临时工作副本)
8192字节(估计的脚本大小)
4096字节(小文件,与大小为4 KB磁盘簇基于相等)
----------------------
176128字节 = 172 KB
(8)问:为什么Windows Installer提示我重新启动计算机?
答:如果Windows Installer需要覆盖一个正在使用的文件,或者安装程序包明确要求Installer重新启动计算机,那么Windows Installer将会提示您重新启动。我们可以很容易地判断出Windows Installer是否是因为需要覆盖一个正在使用的文件而提示您重新启动计算机。我们首先需要生成一个详细日志文件。在这个详细日志文件中,在属性部分中查找是否存在ReplacedInUseFiles属性。如果该属性存在,并且值为1,那么Installer将会因为需要覆盖一个正在使用的文件而提出重新启动计算机的请求。
为了确定哪一个文件正在被使用,请扫描日志文件,查找'Info 1603'和'Info 1903'信息1603信息由InstallValidate操作记录在日志文件中。例如:
MSI (s) (DC:DC): 执行操作: InstallValidate
操作开始 19:55:42: InstallValidate.
…
Info 1603. 文件'd:/test/sample.exe'正在被以下进程使用:名称:sample.exe,Id: 4068,窗口标题:'Sample'。请关闭该程序,然后再试。
一般情况下,出现该消息的同时,也会出现'FilesInUse'(文件正在使用)对话框。但是在使用'安静'UI的情况下,该对话框不会出现。此外,并不是所有正在被使用的文件都会出现在'FilesInUse'对话框中。如果处于使用状态的文件不是一个可执行文件,持有这些文件的进程是一个与安装过程有关的进程,或者持有文件的进程没有一个与之相关的窗口标题,'FilesInUse'对话框都可能不会显示。
安装脚本中的FileCopy opcode也会将Info 1603信息记录在日志中。在上例中,日志文件包含:
MSI (s) (DC:DC):Executing op: FileCopy(SourceName=sample.exe, SourceCabKey=sample.exe, DestName=sample.exe, Attributes=0, FileSize=2044928, PerTick=32768, , VerifyMedia=1, , , , , CheckCRC=0, Version=2.0.2600.0, Language=0, InstallMode=59244544, , , , , , )
…
Info 1603. 文件'D:/test/sample.exe'正在被使用。请关闭程序然后再试。
在文件清理期间的脚本末尾,以下日志文件信息将指出要求用户重新启动计算机的'元凶':
Info 1903. 设定重启日程:删除文件'D:/Config.Msi/12544a31.rbf'。您必须重新启动以完成操作。
尽管文件名为'12544a31.rbf',但实际上它是'Sample.exe'文件。为了安装文件,正在使用的文件会被重新命名为.rbf文件,然后在重新启动后被删除。
(9)问:'ERROR_INSTALL_PACKAGE_VERSION 错误(1613)是什么意思?
答:'ERROR_INSTALL_PACKAGE_VERSION'错误表示:计算机上的Windows Installer不支持本程序包的架构。程序包架构由程序包摘要信息流中的PID_PAGECOUNT属性指出。如果程序包的架构号大于Windows Installer所能够支持的最大架构,您就需要升级Windows Installer的版本或者重新制作该安装程序包,利用较早期的架构对其进行编译。
所有版本的MSI所支持的最小架构号为30。
每个版本的MSI所支持的最大架构号如下:
Windows Installer 1.0: 100
Windows Installer 1.1: 110
Windows Installer 1.2: 120
Windows Installer 2.0: 200
(10)问:在我用系统账户启动一个安装过程的时候,我得到了编号为2103的错误信息,这是为什么?
答:从系统账户(例如计划任务服务)启动程序安装可能会导致2103错误。如果您进行的是一个针对用户的安装,这种情况就会发生。只有针对计算机的安装才能够使用系统账户,因为系统账户不能够对所有必要的用户配置文件夹进行访问。
(11)问:在我从终端服务器上的一个映射驱动器进行安装的时候,为什么出现了2755错误?
答:Windows 2000和更早期的操作系统不支持在终端服务器会话间传递映射驱动器盘符信息。因为Windows Installer服务是在控制台会话中作为一个服务运行,在远程会话中建立的映射驱动器盘对于Windows Installer服务来说是不可见的,从而导致了本错误的出现。只有服务运行于应用程序服务器模式下时才会出现本错误,在远程管理(Remote Admin)模式下不会出现。
注意:Windows XP以及其后的操作系统不存在此限制。
(12)问:在我安装一个使用Web下载启动文件的程序包时,我为什么会得到一个安全性警告对话框,对话框中的消息称'访问在线撤销服务器时发生错误'?
答:安全性警告对话框之所以会出现,是因为在Web下载启动文件(Setup.exe)执行数字签名验证的过程中发生了问题。我们已经通过Windows Installer SDK提供的最新示例代码解决了这个问题,该SDK可以从Microsoft Download Center获得。您只需要使用工具对Setup.exe进行简单的重新配置即可。您可以从SDK Update站点下载该经过修正的示例代码。
参考资料:http://www.it.com.cn/f/edu/046/17/5244_7.htm