为什么 Windows Installer 会需要如此多硬盘空间

有朋友问到 windows\installer 这个目录下的内容为什么占用如此多的硬盘空间,以及是否可以删除的问题,搜索到这篇文章,感觉不错,于是简单翻译了一下发在这里,希望对大家有所帮助。

原文地址:

http://blogs.msdn.com/b/heaths/archive/2008/07/24/why-windows-installer-may-require-so-much-disk-space.aspx

Windows Installer 是一个执行事务型(Transactional)安装的引擎。当首次安装一个产品时,被安装的文件中基本很少已经存在于计算机中,甚至可能完全没有。但当升级或修补某一产品时,则主要是对这些文件进行替换,因此就必须将原始副本保存起来,以便在万一遇到错误时安装程序可以进行回滚。下文介绍了 Windows Installer 为什么需要这么多磁盘空间,以及相关文件都在哪里。

提取出的文件

由于多种原因,可能会需要引导程序(Bootstrap application)。引导程序可能会将安装文件压缩到引导程序本身内部,或者连同安装程序一起包含在一个自解压存档中。引导程序可能还需要直接从网站下载文件到磁盘上某个位置,或间接访问互联网上的文件缓存。

该位置通常位于 %TEMP%

如果提取程序未将这些文件删除,在安装结束后您可以自行删除这些文件。然而要注意,某些安装程序可能会将这些文件注册为源缓存(Source cache)。如果源缓存被删除,但由于某种原因需要提供源内容,Windows Installer 可能会要求提供原始安装文件,或直接导致产品安装失败。

临时本地缓存

如果程序包中包含了完整用户界面,并且该界面会被显示出来,Windows Installer 就会在用户的 %TEMP% 目录下创建 .msi 或 .msp 文件的副本。如果这种安装 – 即客户端安装 – 被提升了权限,则 %TEMP% 将使用进行验证与授权进行安装的用户的对应位置。在 UI 阶段内,Windows Installer 使用该副本计算初始磁盘空间需求,直到开始生成安装脚本。

该副本是其他任何可能被提取到本地硬盘上的临时副本的补充。也就是说,使用 msiexec.exe 或Windows Installer API 调用所引用的程序包会被使用 Windows Installer 生成的文件名复制到 %TEMP%,哪怕源副本已经存在于 %TEMP%中。

该位置位于 %TEMP%

如果 Windows Installer 没有删除这些文件,在安装结束后您可以自行将其删除。

程序包缓存副本

无论是否显示用户界面,安装工作的主要部分 – 也是唯一试图修改计算机状态的这一部分 – 都需要作为服务运行。此时,程序包 – 无论是从任何嵌入的文件中提取出的 .msi 文件,或整个 .msp 文件 – 都会复制到位于 %WINDIR%\Installer 下的 Windows Installer 缓存中。如果安装操作成功完成,该文件依然会保存在这个位置中,这是为了方便以后的维护性安装,包括卸载产品时使用。补丁程序包将会被完整缓存,这也是为了将所有更新过的文件保存起来,方便以后进行任何维护性安装,例如修复或安装后续补丁。

该位置位于 %WINDIR%\Installer

这些文件不能删除,否则以后针对产品进行的维护性安装 – 甚至包括产品的卸载 – 都有可能失败。

安装脚本

Windows Installer 的安装有两个主要阶段:生成安装脚本,然后执行安装脚本。但因为 Windows Installer 是一种事务型安装引擎,因此除非使用 DISABLEROLLBACK属性DisableRollback 系统策略禁用了回滚功能,否则还会生成用于对安装操作进行回滚的第二个脚本。

这些脚本包含了 Windows Installer 将在执行脚本时所要进行的全部操作。 回滚脚本实际上就是这些操作逆向排列后的产物。这些脚本可能会变得相当大,通常这主要取决于产品本身的整体大小。作为一项优化机制,Windows Installer 通常不会重复文件系统目录和注册表键,相反这种情况会分别调用 SetTargetFolder 或 RegOpenKey 操作,这些操作决定了后续的文件或注册表值操作的范围。此外还可以通过安排自定义操作执行类似工作,这样也可以减小磁盘空间需求。

这些脚本会创建到 C:\Config.Msi,其中 C: 是具有最多可用磁盘空间的本地驱动器,但并不一定是系统盘本身。

这些脚本绝对不能删除。当安装完成后,Windows Installer 会将其全部删除,就算安装操作需要重启动多次也会删除。

目标文件、注册表值,以及其他预留的空间

在执行安装脚本时,如果这些资源要复制任何文件,或许该任何注册表值,都将需要占用一定的硬盘空间。在执行 CostFinalize 操作时,Windows Installer 会计算所需硬盘空间的总量。

这些资源会位于提权用户,或最终用户所选的目标位置。

这些资源不能删除;因为这些资源就是所要安装的产品,删除可能导致产品无法启动,或无法正常运行。如果任何资源被删除,您可以使用控制面板中的添加或删除应用程序功能进行修复。

用于回滚的文件副本

因为 Windows Installer 是一种事务型安装引擎,因此如果现有文件将被覆盖,Windows Installer 会对这些文件创建副本。这些文件会与安装脚本一起,创建到一个临时目录中。这些文件并未被压缩,所需存储空间与这些文件被更新前占用的空间一样大。回滚文件更主要是在对产品安装补丁时创建,但并不仅限于安装补丁时。任何产品还可以为其他产品升级文件,这种做法可以通过共享组件的方式进行。

这些资源会被复制到 C:\Config.Msi,其中 C: 是具有最多可用磁盘空间的本地驱动器,但并不一定是系统盘本身。

这些文件不应删除。当安装完成后,Windows Installer 会将其全部删除,就算安装操作需要重启动多次也会删除。

用于补丁安装和删除的基准(Baseline)缓存

Windows Installer 3.0开始支持补丁的卸载操作,为了提供更稳妥的体验,可以为现有文件应用二进制增量(Delta),而无需考虑现有文件可能所处的每个可能的状态。也就是说,如果某个补丁是为了给 foo.dll 应用二进制增量,将 foo.dll v1更新为 foo.dll v2,那么补丁还需要针对安装其他产品后可能更新到 foo.dll v3状态这种情况做出一定的准备,否则安装操作将会失败。

为了让这些功能都尽可能可用,Windows Installer 会将要更新的文件复制到 %WINDIR%\Installer\$PatchCache$ 下每个产品所对应的基准缓存中。大部分情况下,当任何一个版本的文件被首次替换时,这个文件至少会存在两个副本,因为 Windows Installer 会对原始(RTM)版本的文件保留一个副本,并为最近一次小型升级(通常是指“Service Pack”)的更新保存一个副本。

由于 Windows Installer 只将需要更新且将会被覆盖的文件复制到基准缓存中,因此某个文件的基准缓存可能只存在于一个产品中,哪怕更新操作是由针对多个已安装产品所安装的补丁进行更新的。因此在某些产品需要进行更新时,这样的设计可能会导致要求提供原始介质。Windows Installer 4.5 提供了一个功能可以解决该问题,这个功能会将共享的文件复制到所有安装了该文件的产品的基准缓存中 – 因此硬盘空间消耗还将进一步增加。这种做法改善了服务(Servicing)操作,但代价是占用额外的硬盘空间。

这些文件以每个产品为基础,位于 %WINDIR%\Installer\$PatchCache$

这些文件可以删除,或使用 MaxPatchCacheSize 策略禁用基准缓存,但如果这样做,当需要卸载某一补丁,或者需要还原丢失的文件时,如果程序可以显示用户界面,您会被要求提供源文件,否则安装工作会直接失败。

========这是分割线=====

在我个人的观点来看,这里的内容最好不要乱动,虽然需要占据一定的硬盘空间,但换回的是更好的可靠性,以及后续更方便的使用。

然而确实在某些情况下,由于一些程序安装出错或其他原因,可能会产生一定的冗余文件,这种文件完全没什么用,因此可以删除。但也绝对不建议使用手工方式删除。

@Smallfrogs 同学写了一个小程序,可以清理冗余的缓存文件,感兴趣的同学可以试试看。

分享:

《为什么 Windows Installer 会需要如此多硬盘空间》有3个想法

  1. 用了Smallfrogs这个程序之后确实清理出不少磁盘空间,但之后发现好多用windows installer相关的软件都无法卸载了,比如.net4运行库,vmware,提示找不到相应的文件。

    1. 其实这些缓存文件的用途就是这,因此我个人是从来不清理这些内容的,占空间就占吧。

      不过根据介绍,青蛙同学开发的这个工具应该是只清理不需要的冗余文件的,按理说不会影响正常使用的软件,不知道具体是什么原因,建议你联系一下他问问看吧

发表评论

电子邮件地址不会被公开。 必填项已用*标注

发表评论前,先做个简单的数学题吧: * Time limit is exhausted. Please reload CAPTCHA.