0

我们使用 WIX 工具集创建了我们的 MSI 安装程序。我们需要根据用户特定的文件(例如主题和对话)动态自定义安装程序。我们使用此链接将添加内阁文件添加到安装程序 ,但我无法阅读它。我们想知道阅读内阁文件及其文件(自定义文件)的最佳位置。我们应该在自定义操作中执行此操作还是最好的位置是什么?另外,我们需要一个可以遵循的示例代码来完成此任务吗?注意:- 我们的内阁文件将包含很多文件(txt 文件,图像等)

4

1 回答 1

2

我假设,因为您点击了该链接(仍然是我自己的问题)您现在将文件嵌入到 msi 中,作为具有 MediaID 的新文件柜文件

警告:此回复中的代码暂时未经测试

请注意,msi 基本上只是一个数据库,可以使用类似 SQL 的语句进行查询。cabfiles 嵌入在数据库中的 _Streams 表中,可以提取为其原始 cab 文件格式。

您可以使用 ORCA 和 7zip 验证这一点。

您提到的 SO 问题的解决方案旨在“替换”文件。因此在 msi 构建中使用了一个虚拟文件,并且在 wix 中配置了放置。然后在msi构建之后,修改了文件表,将wix生成的原始cab文件的引用更改为注入的新cab文件。通过这种方式,虚拟文件​​是孤立的,但仍嵌入在 msi 中。

如果知道将为每个用户定制哪些文件,并且所有用户都将具有相同的文件夹/文件结构,而与定制无关,则这种方法很好。

我假设每个用户有不同数量的文件,或者每个用户有不同的文件夹结构,因为你不只是复制那个解决方案。要实现这一点,需要编辑几个 msi 表。

目录表: 如果您的 wix 配置尚未定义目录,则需要在此表中创建目录。

像这样的东西应该允许您插入新目录:

    string query = "INSERT INTO `Directory` (`Directory`, `Directory_Parent`, `DefaultDir`) ";
    query += "VALUES ('" + The_Directory_ID + "', '" + The_Parents_ID + "', '" + FolderName + ")";
    pkg.Execute(query);

从这里开始,必须对新 cab 文件中的所有文件重复所有操作

** 成分表 **

您将需要创建一个控制您的文件的组件,以便它可以由 msiexec 安装/卸载。

    string query = "INSERT INTO `Component` (`Component`, `ComponentId`, `Directory_`, `Attributes`, `Condition`, `KeyPath`) ";
    query += "VALUES ('" + The_new_files_name_or_Similar + "', '{" + FileGUID + "}', '" + The_Directory_ID + "0, \"\", "+ A_FILE_ID +" )";
    pkg.Execute(query);

在哪里:

  • FileGUID 可以使用Guid.NewGuid()..
  • A_FILE_ID 可以是文件名,如果 wix 生成 MSI,则所有其他文件通常由“FileID##”引用,因此它可能对您有用,否则您需要确定您可以使用的 FileID 尚未在文件表中..

CreateFolder Table: 通常仅在您需要创建一个空文件夹时才需要,因此我们现在将忽略它,因为您可以在文件夹中转储自述文件或其他内容..

文件表 这个表告诉 msiexec 在你的 msi 中找到文件的位置,以及文件所在的版本,所以它知道是否需要复制它、更新它、忽略它等等。

序列号用于告诉 msi 文件的位置,媒体表将序列与 cab 文件或外部媒体相关联。

该代码也只是一个insert into , 语句:

  • 文件: A_FILE_ID
  • 组件: The_new_files_name_or_Similar
  • 文件名:文件名,(安装时)
  • FileSize:它是文件大小,以字节为单位...
  • 版本:如果文件有版本号,则添加版本号,否则留空。如何检索文件版本取决于文件类型。
  • 语言:这是文件语言版本,通常为 1033,但如果您不知道,可以将其留空。
  • 属性:这取决于媒体文件(机柜)是嵌入的、外部的还是文件是外部的等。使用与 msi 中其他所有内容相同的编号,您通常会没事的。构建后嵌入cabinet文件时,我一直使用512。

然后是魔术部分,我们稍后将不得不使用它:

  • 序列:您需要获取文件表中已经找到的最高序列值,并将其递增

FeatureComponent Table 此表用于将其添加到特征树中,使用户可以添加或删除此特征。所有组件都应该属于一个特征。

  • Feature_安装此组件的功能。你可以做一个新的,也可以不做。我建议您使用现有的!
  • Component_the_new_files_name_or_Similar _

媒体表 您提到的代码已经将一个cabinet文件添加到msi,并在媒体表中创建一个条目:

IList<int> sequences = pkg.ExecuteIntegerQuery("SELECT `LastSequence` FROM `Media` ORDER BY `LastSequence`");
lastIndex = sequences.Count - 1;
int LastSequence = sequences.ElementAt(lastIndex) + numberOfFilesToAdd;
query = "INSERT INTO `Media` (`DiskId`, `LastSequence`, `Cabinet`) VALUES (" + DiskId.ToString() + "," + LastSequence.ToString() + ",'#" + mediaCabinet + "')";
pkg.Execute(query);

所以这应该已经为你设置好了。如果其他人偶然发现了这个答案,我在这里复制了相关的片段,以展示如何为新的 cab 文件制作序列号。

因此文件表的序列号大于 msi 中已有的序列号,但低于您已添加的新媒体中可以找到的序列号。

注意: cab文件中的文件与序号的顺序一致很重要,否则msiexec会抛出找不到文件的错误。

于 2016-04-06T07:18:42.433 回答