是否可以在引导程序中的检测阶段之前从链中的MSI文件中读取MSI属性?

时间:2013-11-05 22:34:55

标签: wix bootstrapper wix3.7 burn

在“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>

1 个答案:

答案 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“);                   
        }
    }
}