14

如何对两个(或多个)MSI 文件进行“内容比较”并查看文件内部的实际不同之处——而不是进行无用的二进制比较?(这显然只告诉我是否正在处理同一文件的副本)。

一些相关和典型的问题场景

  • 我们的构建系统疯狂地吐出 MSI 文件,有时我们需要弄清楚不同 MSI 文件之间存在哪些差异(阅读:发生了一些变化,现在我们部署失败了)。
  • 我们有从不同位置的相同源编译的 MSI 文件,其中一些无法运行报告System.BadImageFormatException - 我们如何调试 MSI 文件中的差异是什么?(在这里专门处理此错误的答案:应用程序是否依赖于编译它的环境?)。
  • MSI 文件可以使用各种工具编译,但对于 stackoverflow 用户来说,此类文件可能最常使用WiXVisual Studio 安装程序项目(免费工具包)创建。

这是一个问答式问题,主题是比较已编译的 MSI 文件以确定存在哪些真正的“内容差异”。

4

1 回答 1

22

Microsoft Orca:如果您安装了 Visual Studio,请尝试在Orca-x86_en-us.msi- 下Program Files (x86)并安装它。然后在开始菜单中找到 Orca。

  • 当前路径C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x86
  • 根据需要更改版本号

About MSI Files

粗略地说,MSI文件是COM 结构的存储文件- 本质上是文件中的文件系统 - 具有不同内容的流,其中一个是精简的SQL Server 数据库(我认为是最通用的术语)。如果 MSI 文件是可读的,则可以比较(各种格式和类型的)内容。

技术说明:可以想象,触发 a 的 MSISystem.BadImageFormatException是不可运行的(msiexec.exe无法运行),但它可能仍然可读 - 因此具有可比性(如果您遇到过,请添加评论以验证这一点)。

Streams : MSI 中的一些是带有字符串值的表。也可能存在用于存储要部署的文件的嵌入式 cab 存档的流,以及仅具有二进制内容的表- 例如已Binary table编译和未编译的自定义操作等与设置所需的其他二进制内容一起存储的位置。还有一个特殊的“摘要流”和一个表格,其中的图标以它们的原生二进制格式存储,并且列表还在继续……对于大多数表格,我们可以比较每个表格中的字符串,就像我们比较文本中的文本一样一个 Word 文档(也曾经是 OLE / COM 文件- 尽管现在较新的版本使用Open Office XML) 并获得详细的差异报告。为了做到这一点,您显然需要一个专用工具来完成这项工作——一个能够在所有相关流中找到方法的工具。下面列出了一些商业和免费工具。

二进制内容:在详细说明之前,我应该注意,比较Binary Table, Cabs Table, Icon Table- 或任何其他二进制表中的内容通常只允许您进行二进制比较(特别是对于已编译的自定义操作 dll 和 exe 文件)。脚本自定义操作- 在二进制表中 - 可以作为文本进行比较,但编译的自定义操作仅是二进制比较。因此,如果您的问题源自已编译的自定义操作,则您无法在直接比较中真正看到它(您只看到二进制差异)。您需要访问您的源代码控制系统以查看用于编译的任何类型的自定义操作的代码- 希望您有一个良好的标签实践因此您可以找到每个设置中使用的实际源代码。我不使用这种做法,但对于内部的企业版本,也许您甚至可以为编译的自定义操作包含调试构建 dll,并尝试将调试器附加到正在运行的代码以真正弄清楚发生了什么?不过,我不会将调试模式 dll 用于公开发布 - 除非我澄清了任何风险。调试代码可能充斥着(意外的)调试消息框(用作附加调试器的入口点)和其他不应该出现在生产包中的问题。

想一想,您的 cab 文件和图标文件绝对可以通过使用dark.exe以下描述的反编译 MSI 文件的技术与旧(或新)MSI 文件中的相应版本进行比较。然后,使用一个好的比较工具(Beyond Compare 将在下面提到),您可以对不同 MSI 版本之间的 cab 文件内容进行完整的比较(并且某些文件可能是文本文件,可以进行文本比较)。我猜出租车和图标是一种开放格式的“透明二进制文件”,而不是编译的二进制文件(具有自定义操作等),它们本质上是不可反编译或可检查的(除非您知道如何反编译托管二进制文件)。

总之MSI 文件是完全透明的,除了编译的自定义操作这种透明度是 MSI 的核心优势之一。与以前的部署技术相比,大多数 Windows Installer 优势通常集中在企业部署优势上。不幸的是,开发人员可能只看到了 MSI 的坏方面:(潜在的)MSI 反模式(接近底部 - 目前非常混乱和临时)。诚然,其中一些问题非常严重,违反了“最小惊讶原则”。开发人员 - 为什么还有其他同样重要的事情要做 - 坦率地说,他们可能会难以置信地摸不着头脑。

不过请不要误会:MSI 具有巨大的企业部署优势(参见与上面相同的链接,朝向底部)。精简:可靠的静默运行、远程管理、回滚、日志记录、隐式卸载功能、提升权限、标准化命令行、透明度、标准化设置自定义转换和管理员安装以可靠地提取文件。只是为了快速命名大的。列表形式的好处在这里

到目前为止有很多题外话——让我们进入正题。可以使用哪些工具来比较 MSI 文件?


Commercial Tools

一些商业部署工具,如InstallshieldAdvanced Installer许多其他 MSI 工具都支持查看和比较 MSI 文件。也许我添加了太多链接,但让我使用我通常的“如果你链接到一个,你链接到每个人”的策略 - 它应该节省一些时间和一些谷歌搜索。

作为一个特别的说明 - 一个怀旧的 - 我见过的最好的 MSI-diff 功能是在Wise Package Studio中。老实说,它比其他人都高出一筹——总是在工作,颜色编码整齐,而且很容易理解。此工具不再出售,如下所述:要使用什么安装产品?InstallShield、WiX、Wise、Advanced Installer 等(如果您的公司中有打包团队,也许他们有备用许可证?)。


Free Tools

商业工具很好,但也有一些免费的替代品可用于比较 MSI 文件 - 下面是其中一些工具的列表以及如何使用每个工具的一些提示(以相当简约的方式)。

添加了更多细节dark.exe- 这根本不是 COM 结构存储文件的比较工具,而是一种将 MSI 文件反编译为 WiX XML 源文件并提取所有支持文件(图标、二进制文件、cabs、设置文件)的方法- 允许之后将它们与常规文本/二进制比较工具进行比较。

1.Orca (MSI SDK)

微软自己的名为Orca的MSI SDK 工具/查看器可以查看 MSI 文件并对其进行编辑,但没有直接支持比较两个 MSI 文件(据我所知)。我想您可以导出表格然后比较它们,但其他工具具有更多内置功能。之所以提到此选项,是因为您可能已经安装了 Orca,然后这可能是完成简单 diff 的一种快速方法。“穷人的选择”。

您可能已经有了安装程序。如果您安装了 Visual Studio,请尝试在Orca-x86_en-us.msi- 下搜索Program Files (x86)并安装它。然后在开始菜单中找到 Orca。从技术上讲,Orca 是作为Windows SDK 的一部分安装的(大,但免费下载)。如果您没有安装 Visual Studio,也许您认识有人安装?只需让他们搜索此 MSI 并将其发送给您(这是一个很小的半 mb 文件)- 应该花费他们几秒钟的时间。如果没有,您可以随时下载 Windows SDK

2.Super Orca (free third party tool)

Super Orca 将允许对两个 MSI 文件进行初步比较。我的冒烟测试似乎表明可以忽略摘要流等高级字段。换句话说,一个直表只比较。可能还有其他限制。也许它已经足够好了?它很容易使用。

注意:我无法确定验证,但我相信这个工具在没有警告的情况下保存了我的 MSI。这在当时是非常不可取的。

3.widiffdb.vbs (MSI SDK)

有一个 VBScript,您可以使用它来查看两个 MSI 文件之间的MSI SDK差异。它被称为widiffdb.vbs( msdn )。使用此工具,我可以看到 Super Orca 忽略的摘要流差异。任何 MSI SDK 都是权威的。

更新 github.com 上的所有 MSI SDK API 脚本(实际的 VBScript 代码)。

  • 提供指向此类 MSI SDK VBScript 完整列表的链接- 用于各种目的。不要混淆,仅widiffdb.vbs用于比较 MSI 文件,但有许多有用的脚本可用于其他目的。
  • 如果您安装了 Visual Studio,只需搜索widiffdb.vbs. 启动cscript.exe并传入两个 MSI 文件的完整路径以进行比较。在控制台中输出。

用法:

cscript.exe widiffdb.vbs "Setup 1.msi" "Setup 2.msi"

样本输出:

Property Value           [ALLUSERS] {1}->{2}
Property Value           [MSIINSTALLPERUSER] {}->{1}
Property INSERT          [MSIINSTALLPERUSER]
\005SummaryInformation   [9] {{00000000-0000-0000-0000-000000000000}}->{{00000000-0000-0000-0000-000000000001}}
\005SummaryInformation   [12] {28.03.2019 15:20:02}->{28.03.2019 14:40:52}
\005SummaryInformation   [13] {28.03.2019 15:20:02}->{28.03.2019 14:40:52}
\005SummaryInformation   [15] {2}->{10}

Program Files (x86)要查找脚本,您可以在是否安装了 Visual Studio下搜索它(它是 Windows SDK 的一部分,也将与 Visual Studio 一起安装) - (当前路径是: C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x86- 只需适当地替换版本号并且您应该更快地找到 MSI)。

4.dark.exe (WiX toolkit - open source)

WiX 工具集中的dark.exe二进制文件(可能用于编译某些 MSI 文件的工具包)。这是 MSI 文件的“反汇编程序”或“反编译程序”。它将 MSI 文件转换为XML 格式(首先用于编译 MSI 文件的 WiX 自己的格式)以及许多提取的二进制文件(如果您使用正确的反编译选项和标志)。dark.exewxs

wxs源文件可以作为常规文本源文件进行比较(我最喜欢的工具是Beyond Compare,但它是一个商业工具 - 有很多文本比较工具 - 包括 Visual Studio 中的那些)。二进制文件显然可以进行二进制比较。例如,任何提取的 CAB 文件都可以与来自另一个 MSI 安装版本的另一个类似的 cab 文件进行比较。

这是一个示例命令行:

dark.exe -x outputfolder MySetup.msi
  • 在许多情况下,这将产生非常好的 MSI 文件比较,您应该能够确定真正不同的是什么。

  • 提取的二进制文件可以是脚本文件(VBScript 等)或任意数量的其他二进制文件(例如编译的 DLL 自定义操作)。在后一种情况下,您无法真正进一步反编译它 - 除非它是 .NET 二进制文件并且您具有反编译此类二进制文件的专业知识。

  • 但是,应该注意的是,使用完全相同的 WiX 源文件编译的 WiX 生成的 MSI 文件可能会因以下几个原因而有所不同:

    • 相同的 WiX 源文件也可以使用不同的编译器链接器设置进行编译,这会以多种不同的方式影响生成的 MSI 文件。要查看所有开关,请下载并安装 WiX,然后将candle.exelight.exe写入命令提示符并点击enter.

    • 某些字段(例如包 GUID产品 GUID )可以设置为在 wxs 文件中自动生成。在这种情况下,对于每个构建,生成的 MSI 文件中的相应字段显然会有所不同。

      • 我没有关于此时可以设置为自动生成哪些字段的完整列表(如果您知道,可以点击编辑并就地修改)。

      • 提到的自动生成的字段也可以是硬编码的(这对包 GUID 不利,但这是另一个很长的故事 - 只要知道如果您发现两个具有相同包 GUID 的二进制不同的 MSI 文件,那么你遇到了严重的麻烦 - 如果它们在野外 - Windows Installer 将根据定义将它们视为同一个文件)。包代码应始终自动生成。题外话。

    • MSI 文件本身显然具有不同的文件日期信息,已分别编译 - 只是为了说明这一点。

还有一个与当前主题有些无关但重要的特别说明:您可以使用它dark.exe来反编译使用 WiX 的刻录功能编译的可执行文件。这是 WiX 的引导程序功能,用于依次安装一个或多个 MSI 和/或 EXE 文件 - 一个接一个。这些引导程序是 EXE 文件,您可以将它们解压缩到其组成的 MSI 和/或 EXE 文件中:

dark.exe -x outputfolder setup.exe

只需打开命令提示符,CD 到 setup.exe 所在的文件夹。然后指定上面的命令。具体样品:dark.exe -x outputfolder MySetup.exe。输出文件夹将包含几个子文件夹,其中包含提取的 MSI 和 EXE 文件以及 Burn GUI 的清单和资源文件。然后可以如上所述反汇编任何 MSI 文件以生成 WiX 源文件 (wxs)。

5.InstEd (free third party tool - with plus version available)

出于某种原因,我从未积极使用过这个工具,但测试了几次。再次测试它似乎确实可以比较两个 MSI 文件,尽管来自一个奇怪的菜单选项(这让我认为该功能以前不起作用)。

  • 打开一个 MSI,然后转到Transform => Compare Against...并浏览到要与第一个比较的 MSI。
  • 比较似乎没问题,我看到摘要流中有变化 - 例如 - 但差异似乎没有显示出什么不同(除非我只是看不到它)。
  • 要查看摘要流更改,请在单独的 InstEd 实例中打开这两个文件并进入Tables => Summary Info...这两个实例。现在比较属性表中的信息。或者使用widiffdb.vbs上面列出的脚本。

6.Other Tools... (COM-structured storage file viewers)

毫无疑问,还有许多其他工具能够查看 COM 结构的存储文件,但我认为上述选项对于大多数用户来说应该足够了。我将再次添加指向installsite.org 的 MSI 工具列表的链接。

7.Advanced Installer (commercial tool with some free features)

这个商业工具将能够用作查看器,并允许对 MSI 文件进行一些基本操作,即使没有使用完整许可证运行。好的一点是您甚至不需要使用原始表,而是可以使用更好的用户界面来“修复”MSI 中的各种内容。例如各种升级参数(主要升级卸载失败时继续或失败等...)。

在表编辑器视图(直线表视图)中所做的更改在其他“向导视图”中将不可见。原因在这里解释


链接

于 2018-01-28T02:16:09.550 回答