在“Bundle.wxs”中,我有一个带有“MsiPackages”的“链”,其中包含“InstallConditions”。为了让用户决定他/她想要安装/升级哪些软件包,我想显示在其中找到的属性。
例如,我想在链中每个MSI的“Property”表中读取属性“ProductName”和“ProductVersion”,并将其显示给链中每个MSI的复选框旁边的用户。该复选框连接到“InstallConditions”中使用的刻录变量。
但问题是,在“应用”步骤之前,我似乎无法访问MSI文件。在此步骤之前,不会从Bootstrapper Application EXE中提取它们。所以,我的问题是,有没有办法以编程方式加载这些值,以便在Apply步骤之前将它们显示给用户?我可以使用变量并使用值填充它们,但是这些信息已经在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>
答案 0 :(得分:4)
WiX确实会生成一个BootstrapperApplicationData.xml文件,其中包含许多用于构建exe的信息,并包含在运行时可用的文件中。您可以在运行时解析该文件以访问该元数据。由于该文件以及我们的所有程序集和.msi文件都放在一个随机名称的临时文件夹中,因此我们无法提前知道文件所在的位置,因此我们必须使用程序集的路径来查找它。然后,您可以解析XML以获取元数据。
我的博客文章中包含其他详细信息:https://www.wrightfully.com/part-3-of-writing-your-own-net-based-installer-with-wix-context-data/
在我的情况下,我使用的是代码而不是&#39;&#39;所以我可以使用的某些信息可能不适合您,因此您的体验可能会有所不同。我建议在调试模式下运行一个临时安装程序,并设置一个断点来检查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“);
}
}
}