从PackageID获取显示名称

时间:2012-10-11 18:44:30

标签: wix wix3.6 bootstrapper burn

查看Wix Standard Bootstrapper应用程序的来源,似乎每个包都有 DisplayName 属性:

pPackage->sczDisplayName

但是,WiX安装项目中使用的BootstrapperCore dll没有此属性。有没有办法从托管代码中的包中提取此属性?

2 个答案:

答案 0 :(得分:11)

我将Bal代码移植到C#中,尝试使其与C ++代码完全相同:

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Xml;
using System.Xml.XPath;

public class BootstrapperApplicationData
{
    public const string defaultFileName = "BootstrapperApplicationData.xml";
    public const string xmlNamespace = 
        "http://schemas.microsoft.com/wix/2010/BootstrapperApplicationData";

    private static DirectoryInfo defaultFolder;
    public static DirectoryInfo DefaultFolder
    {
        get
        {
            if (defaultFolder == null)
            {
                defaultFolder = (new FileInfo(Assembly.GetExecutingAssembly().Location)).Directory;
            }
            return defaultFolder;
        }
    }

    private static FileInfo defaultFile;
    public static FileInfo DefaultFile
    {
        get
        {
            if (defaultFile == null)
            {
                defaultFile = new FileInfo(Path.Combine(DefaultFolder.FullName, defaultFileName));
            }
            return defaultFile;
        }
    }

    public FileInfo DataFile { get; protected set; }
    public Bundle Data { get; protected set; }

    public BootstrapperApplicationData() : this(DefaultFile) { }

    public BootstrapperApplicationData(FileInfo fiBootstrapperApplicationData)
    {
        DataFile = fiBootstrapperApplicationData;
        using (FileStream fs = DataFile.OpenRead())
        {
            Data = ParseBundleFromStream(fs);
        }
    }

    public static Bundle ParseBundleFromStream(Stream stream)
    {
        XPathDocument manifest = new XPathDocument(stream);
        XPathNavigator root = manifest.CreateNavigator();
        return ParseBundleFromXml(root);
    }

    public static Bundle ParseBundleFromXml(XPathNavigator root)
    {
        Bundle bundle = new Bundle();

        XmlNamespaceManager namespaceManager = new XmlNamespaceManager(root.NameTable);
        namespaceManager.AddNamespace("p", xmlNamespace);
        XPathNavigator bundleNode = root.SelectSingleNode("/p:BootstrapperApplicationData/p:WixBundleProperties", namespaceManager);

        if (bundleNode == null)
        {
            throw new Exception("Failed to select bundle information");
        }

        bool? perMachine = GetYesNoAttribute(bundleNode, "PerMachine");
        if (perMachine.HasValue)
        {
            bundle.PerMachine = perMachine.Value;
        }

        string name = GetAttribute(bundleNode, "DisplayName");
        if (name != null)
        {
            bundle.Name = name;
        }

        string logVariable = GetAttribute(bundleNode, "LogPathVariable");
        if (logVariable != null)
        {
            bundle.LogVariable = logVariable;
        }
        else
        {
            //wix would actually debug "Failed to select bundle information" and return with E_NOTFOUND, but I think it's a (harmless) bug
        }

        Package[] packages = ParsePackagesFromXml(root);
        bundle.Packages = packages;

        return bundle;
    }

    public static Package[] ParsePackagesFromXml(XPathNavigator root)
    {
        List<Package> packages = new List<Package>();

        XmlNamespaceManager namespaceManager = new XmlNamespaceManager(root.NameTable);
        namespaceManager.AddNamespace("p", xmlNamespace);
        XPathNodeIterator nodes = root.Select("/p:BootstrapperApplicationData/p:WixPackageProperties", namespaceManager);

        foreach (XPathNavigator node in nodes)
        {
            Package package = new Package();

            string id = GetAttribute(node, "Package");
            if (id == null)
            {
                throw new Exception("Failed to get package identifier for package");
            }
            package.Id = id;

            string displayName = GetAttribute(node, "DisplayName");
            if (displayName != null)
            {
                package.DisplayName = displayName;
            }

            string description = GetAttribute(node, "Description");
            if (description != null)
            {
                package.Description = description;
            }

            PackageType? packageType = GetPackageTypeAttribute(node, "PackageType");
            if (!packageType.HasValue)
            {
                throw new Exception("Failed to get package type for package");
            }
            package.Type = packageType.Value;

            bool? permanent = GetYesNoAttribute(node, "Permanent");
            if (!permanent.HasValue)
            {
                throw new Exception("Failed to get permanent settings for package");
            }
            package.Permanent = permanent.Value;

            bool? vital = GetYesNoAttribute(node, "Vital");
            if (!vital.HasValue)
            {
                throw new Exception("Failed to get vital setting for package");
            }
            package.Vital = vital.Value;

            bool? displayInternalUI = GetYesNoAttribute(node, "DisplayInternalUI");
            if (!displayInternalUI.HasValue)
            {
                throw new Exception("Failed to get DisplayInternalUI setting for package");
            }
            package.DisplayInternalUI = displayInternalUI.Value;

            string productCode = GetAttribute(node, "ProductCode");
            if (productCode != null)
            {
                package.ProductCode = productCode;
            }

            string upgradeCode = GetAttribute(node, "UpgradeCode");
            if (upgradeCode != null)
            {
                package.UpgradeCode = upgradeCode;
            }

            string version = GetAttribute(node, "Version");
            if (version != null)
            {
                package.Version = version;
            }

            packages.Add(package);
        }

        return packages.ToArray();
    }

    public static string GetAttribute(XPathNavigator node, string attributeName)
    {
        XPathNavigator attribute = node.SelectSingleNode("@" + attributeName);

        if (attribute == null)
        {
            return null;
        }

        return attribute.Value;
    }

    public static bool? GetYesNoAttribute(XPathNavigator node, string attributeName)
    {
        string attributeValue = GetAttribute(node, attributeName);

        if (attributeValue == null)
        {
            return null;
        }

        return attributeValue.Equals("yes", StringComparison.InvariantCulture);
    }

    public static PackageType? GetPackageTypeAttribute(XPathNavigator node, string attributeName)
    {
        string attributeValue = GetAttribute(node, attributeName);

        if (attributeValue == null)
        {
            return null;
        }

        if (attributeValue.Equals("Exe", StringComparison.InvariantCulture))
        {
            return PackageType.EXE;
        }
        else if (attributeValue.Equals("Msi", StringComparison.InvariantCulture))
        {
            return PackageType.MSI;
        }
        else if (attributeValue.Equals("Msp", StringComparison.InvariantCulture))
        {
            return PackageType.MSP;
        }
        else if (attributeValue.Equals("Msu", StringComparison.InvariantCulture))
        {
            return PackageType.MSU;
        }
        else
        {
            return 0;
        }
    }

    public enum PackageType
    {
        EXE,
        MSI,
        MSP,
        MSU,
    }

    public class Package
    {
        public string Id;
        public string DisplayName;
        public string Description;
        public PackageType Type;
        public bool Permanent;
        public bool Vital;
        public bool DisplayInternalUI;

        //not available until WiX 3.9.421.0
        public string ProductCode;
        public string UpgradeCode;
        public string Version;
    }

    public class Bundle
    {
        public bool PerMachine;
        public string Name;
        public string LogVariable;
        public Package[] Packages;
    }
}

答案 1 :(得分:5)

在构建过程中生成的BootstrapperApplicationData.xml文件放在BA .dll旁边。您可以加载该XML文件以获取有关捆绑包和捆绑包中的大量信息。

要在本机代码中加载BootstrapperApplicationData.xml,请使用随WiX工具集提供的BalManifestLoad()中的balutil.lib方法。您可以在src\ext\BalExtension\balutil\balutil.cpp中看到代码。然后,您也可以在BalInfoParseFromXml()中使用balutil.lib将XML文件解析为一堆方便的结构。您可以在src\ext\BalExtension\balutil\balinfo.cpp

中查看代码
相关问题