【问题标题】:Getting Display Name from PackageID从 PackageID 获取显示名称
【发布时间】:2012-10-11 18:44:30
【问题描述】:

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

pPackage->sczDisplayName

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

【问题讨论】:

    标签: wix wix3.6 bootstrapper burn


    【解决方案1】:

    我将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;
        }
    }
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 感谢您提供此信息。我们可以查询它以获取显示名称,因为我们已经在不同的事件/方法中提供了 PackageId。
      • 但是您不认为,显示名称或应用程序名称应该像 PackageId、ProductCode 等一样可用吗?
      • 我们尽可能减少引擎和 BootstrapperApplication 之间的接口,因为它定义了一个在我们添加/删除/更改它时会中断的合约。应用程序数据清单不是接口契约,因此我们可以根据需要进行扩展。换句话说,界面有必要的数据来查找所有其他数据。
      猜你喜欢
      • 2020-03-02
      • 1970-01-01
      • 1970-01-01
      • 2019-10-22
      • 2023-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-19
      相关资源
      最近更新 更多