是否可以在引导程序中的检测阶段之前从链中的 MSI 文件中读取 MSI 属性?
Posted
技术标签:
【中文标题】是否可以在引导程序中的检测阶段之前从链中的 MSI 文件中读取 MSI 属性?【英文标题】:Is it possible to read MSI properties from MSI files in chain before detect phase in bootstrapper? 【发布时间】:2013-11-05 22:34:54 【问题描述】:在“Bundle.wxs”中,我有一个带有“MsiPackages”的“链”,其中包含“InstallConditions”。为了让用户决定他/她想要安装/升级哪些包,我想显示其中的属性。
例如,我想读取链中每个 MSI 的“属性”表中的属性“ProductName”和“ProductVersion”,并在链中每个 MSI 的复选框旁边将其显示给用户。该复选框连接到“InstallConditions”中使用的刻录变量。
但问题是,在“应用”步骤之前,我似乎无法访问 MSI 文件。在此步骤之前,它们不会从引导程序应用程序 EXE 中提取。所以,我的问题是,有没有办法以编程方式加载这些值,以便在应用步骤之前将它们显示给用户?我可以使用变量并自己用这些值填充它们,但这些信息已经在 MSI 中,所以这似乎效率低下。
有没有办法做到这一点?感谢您的帮助。
<Bundle>
<Variable Name="InstallProduct1" Type="string" Value="true" />
<Variable Name="ProductName1" Type="string" Value="My Product 1"/> <!-- Better way? -->
<Variable Name="ProductVersion1" Type="version" Value="1.2.3.4"/> <!-- Better way? -->
<Chain>
<MsiPackage SourceFile="my_product_1.msi"
InstallCondition="InstallProduct1">
</MsiPackage>
</Chain>
</Bundle>
【问题讨论】:
【参考方案1】:WiX 确实会生成一个 BootstrapperApplicationData.xml 文件,其中包含大量用于构建 exe 的信息,并且包含在运行时可用的文件中。您可以在运行时解析该文件以访问该元数据。由于该文件以及我们所有的程序集和 .msi 文件都放置在一个随机命名的临时文件夹中,因此我们无法提前知道该文件的位置,因此我们必须使用程序集的路径来找到它。然后,您可以解析 XML 以获取元数据。
我在这里有一篇博文,其中包含更多详细信息:https://www.wrightfully.com/part-3-of-writing-your-own-net-based-installer-with-wix-context-data/
在我的例子中,我使用标签而不是 '',所以有一些可用的信息可能不适合您,因此您的体验可能会有所不同。我建议在调试模式下运行临时安装程序并设置断点来检查 XML 的内容,以获得可用内容的完整列表。
这是我如何从 ManagedBootstrapperApplication (c#) 中的文件获取数据的示例。注意:在这个例子中,我的领域对象是 MBAPrereqPackage、BundlePackage 和 PackageFeature,它们每个都在它们的构造函数中获取一个 XML 节点对象,并进一步将数据解析为对象的属性。
const XNamespace ManifestNamespace = ( XNamespace) “http://schemas.microsoft.com/wix/2010/BootstrapperApplicationData” ;
public void Initialize()
//
// parse the ApplicationData to find included packages and features
//
var bundleManifestData = this.ApplicationData;
var bundleDisplayName = bundleManifestData
.Element(ManifestNamespace + “WixBundleProperties“ )
.Attribute( “DisplayName“)
.Value;
var mbaPrereqs = bundleManifestData.Descendants(ManifestNamespace + “WixMbaPrereqInformation“)
.Select(x => new MBAPrereqPackage(x))
.ToList();
//
//exclude the MBA prereq packages, such as the .Net 4 installer
//
var pkgs = bundleManifestData.Descendants(ManifestNamespace + “WixPackageProperties“)
.Select(x => new BundlePackage(x))
.Where(pkg => !mbaPrereqs.Any(preReq => preReq.PackageId == pkg.Id));
//
// Add the packages to a collection of BundlePackages
//
BundlePackages.AddRange(pkgs);
//
// check for features and associate them with their parent packages
//
var featureNodes = bundleManifestData.Descendants(ManifestNamespace + “WixPackageFeatureInfo“);
foreach ( var featureNode in featureNodes)
var feature = new PackageFeature(featureNode);
var parentPkg = BundlePackages.First(pkg => pkg.Id == feature.PackageId);
parentPkg.AllFeatures.Add(feature);
feature.Package = parentPkg;
///
/// Fetch BootstrapperApplicationData.xml and parse into XDocument.
///
public XElement ApplicationData
get
var workingFolder = Path.GetDirectoryName(this.GetType().Assembly.Location);
var bootstrapperDataFilePath = Path.Combine(workingFolder, “BootstrapperApplicationData.xml”);
using (var reader = new StreamReader(bootstrapperDataFilePath))
var xml = reader.ReadToEnd();
var xDoc = XDocument.Parse(xml);
return xDoc.Element(ManifestNamespace + “BootstrapperApplicationData“);
【讨论】:
谢谢!我会试试看!以上是关于是否可以在引导程序中的检测阶段之前从链中的 MSI 文件中读取 MSI 属性?的主要内容,如果未能解决你的问题,请参考以下文章