Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WIX:使用DTF以编程方式向msi安装程序添加和读取CAB文件,以允许安装程序的动态自定义_C#_.net_Wix_Windows Installer_Dtf - Fatal编程技术网

C# WIX:使用DTF以编程方式向msi安装程序添加和读取CAB文件,以允许安装程序的动态自定义

C# WIX:使用DTF以编程方式向msi安装程序添加和读取CAB文件,以允许安装程序的动态自定义,c#,.net,wix,windows-installer,dtf,C#,.net,Wix,Windows Installer,Dtf,我们使用WIX工具集创建了MSI安装程序。我们需要根据用户特定的文件(如主题和对话)动态定制安装程序。 我们使用此链接添加 但我不能读。 我们想知道读取CAB文件及其文件(自定义文件)的最佳位置。 我们应该在定制活动中这样做,还是在什么地方这样做最好? 此外,我们需要一个样本代码,我们可以按照实现这项任务? 注意:-我们的CAB文件将包含大量文件(txt文件、图像等)我假设,由于您遵循了该链接(尽管我自己的问题如此),您现在将这些文件作为带有MediaID的新CAB文件嵌入到msi中 警告:此回

我们使用WIX工具集创建了MSI安装程序。我们需要根据用户特定的文件(如主题和对话)动态定制安装程序。 我们使用此链接添加 但我不能读。 我们想知道读取CAB文件及其文件(自定义文件)的最佳位置。 我们应该在定制活动中这样做,还是在什么地方这样做最好? 此外,我们需要一个样本代码,我们可以按照实现这项任务?
注意:-我们的CAB文件将包含大量文件(txt文件、图像等)

我假设,由于您遵循了该链接(尽管我自己的问题如此),您现在将这些文件作为带有MediaID的新CAB文件嵌入到msi中

警告:此回复中的代码目前尚未测试

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

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

您提到的问题的解决方案旨在“替换”文件。 因此,在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);
其中:

  • 可以使用
    Guid.NewGuid()
    生成文件Guid
  • _FILE_ID可以是文件名,如果wix生成MSI,所有其他文件通常由“FileID###”引用,因此它可能适合您,否则您需要确定您可以使用的文件表中不存在的文件ID
创建文件夹表: 通常只有在需要创建空文件夹时才需要,因此我们暂时忽略此项,因为您可以在文件夹中转储自述文件或其他内容

文件表 此表告诉msiexec在msi中的位置以及文件的版本,以便它知道是否需要复制、更新、忽略等

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

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

  • 文件:文件ID
  • 组件:新文件名或类似文件名
  • 文件名:文件名(安装时)
  • 文件大小:它是文件大小,以字节为单位
  • 版本:如果文件有版本号,请添加版本号,否则留空。如何检索文件版本取决于文件类型
  • 语言:这是文件语言版本,通常为1033,但如果您不知道,可以将其保留为空
  • 属性:这取决于媒体文件(文件柜)是嵌入的、外部的还是外部的,等等。。使用与msi中其他所有内容相同的数字,您通常会没事。在构建后嵌入CAB文件时,我总是使用512
然后是魔术部分,我们将在稍后使用:

  • 序列:您需要获取文件表中已找到的最高序列值,并将其递增
功能组件表 此表用于将此功能添加到功能树中,使用户可以添加或删除此功能。 所有组件都应属于一个特征

  • 功能安装此组件的功能。你可以做一个新的,也可以不做。我建议您使用现有的一个
  • 组件新文件名或类似文件
媒体表 您提到的代码已将CAB文件添加到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);
IList sequences=pkg.ExecuteIntegerQuery(“通过`LastSequence``从`Media`顺序中选择`LastSequence`”);
lastIndex=序列。计数-1;
int LastSequence=sequences.ElementAt(lastIndex)+要添加的文件数;
query=“插入到`Media`(`DiskId`、`LastSequence`、`Cabinet`)值(“+DiskId.ToString()+”、“+LastSequence.ToString()+”、'#“+mediacainet+”)”;
pkg.Execute(查询);
所以这应该已经为您设置好了。。 如果其他人偶然发现了这个答案,我会在这里复制相关的代码片段,以展示如何为新的cab文件生成seuquence编号

因此,文件表的序列号大于msi中已有的序列号,但低于已添加的新介质中的序列号

注意:cab文件中的文件与序列号的顺序相同非常重要,否则msiexec可能会抛出无法找到文件的错误。