示例#1
0
        /// <summary>
        /// Removes properties defined by this extension.
        /// </summary>
        /// <param name="tables">The collection of tables.</param>
        private void FinalizeProperties()
        {
            string[] properties = new string[] { "DISABLEDEPENDENCYCHECK", "IGNOREDEPENDENCIES" };
            foreach (string property in properties)
            {
                Wix.Property elem = this.Core.GetIndexedElement("Property", property) as Wix.Property;
                if (null != elem)
                {
                    // If a value is defined, log a warning we're removing it.
                    if (!String.IsNullOrEmpty(elem.Value))
                    {
                        this.Core.OnMessage(DependencyWarnings.PropertyRemoved(elem.Id));
                    }

                    // If the property row was found, remove it from its parent.
                    if (null != elem.ParentElement)
                    {
                        Wix.IParentElement elemParent = elem.ParentElement as Wix.IParentElement;
                        if (null != elemParent)
                        {
                            elemParent.RemoveChild(elem);
                        }
                    }
                }
            }
        }
示例#2
0
        /// <summary>
        /// Decompiles the WixDependencyRef table.
        /// </summary>
        /// <param name="table">The table to decompile.</param>
        private void DecompileWixDependencyRefTable(Table table)
        {
            foreach (Row row in table.Rows)
            {
                RequiresRef requiresRef = new RequiresRef();

                requiresRef.Id = (string)row[1];

                Provides provides = (Provides)this.Core.GetIndexedElement("WixDependencyProvider", (string)row[0]);
                if (null != provides)
                {
                    provides.AddChild(requiresRef);
                }
                else
                {
                    this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "WixDependencyProvider_", (string)row[0], "WixDependencyProvider"));
                }

                // Get the cached keys for the provider and dependency IDs and generate registry rows.
                string providesKey = null;
                string requiresKey = null;

                if (null != provides && this.keyCache.ContainsKey(provides.Id))
                {
                    providesKey = this.keyCache[provides.Id];
                }
                else
                {
                    this.Core.OnMessage(DependencyWarnings.ProvidesKeyNotFound(row.SourceLineNumbers, provides.Id));
                }

                if (this.keyCache.ContainsKey(requiresRef.Id))
                {
                    requiresKey = this.keyCache[requiresRef.Id];
                }
                else
                {
                    this.Core.OnMessage(DependencyWarnings.RequiresKeyNotFound(row.SourceLineNumbers, requiresRef.Id));
                }

                if (!this.Core.EncounteredError)
                {
                    // Add the dependency-specific registry keys to be removed during finalization.
                    // Only remove specific keys that the compiler writes.
                    string keyRequires = String.Format(@"{0}{1}\{2}\{3}", DependencyCommon.RegistryRoot, requiresKey, DependencyCommon.RegistryDependents, providesKey);

                    this.registryValues.Add(keyRequires, "*");
                    this.registryValues.Add(keyRequires, "MinVersion");
                    this.registryValues.Add(keyRequires, "MaxVersion");
                    this.registryValues.Add(keyRequires, "Attributes");
                }
            }
        }
示例#3
0
        /// <summary>
        /// Processes a child element of a Component for the Compiler.
        /// </summary>
        /// <param name="parentElement">Parent element of element to process.</param>
        /// <param name="element">Element to process.</param>
        /// <param name="context">Extra information about the context in which this element is being parsed.</param>
        /// <returns>The component key path type if set.</returns>
        public override ComponentKeyPath ParsePossibleKeyPathElement(XElement parentElement, XElement element, IDictionary <string, string> context)
        {
            SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(parentElement);
            ComponentKeyPath keyPath           = null;

            switch (parentElement.Name.LocalName)
            {
            case "Component":
                string componentId = context["ComponentId"];

                // 64-bit components may cause issues downlevel.
                bool win64 = false;
                Boolean.TryParse(context["Win64"], out win64);

                switch (element.Name.LocalName)
                {
                case "Provides":
                    if (win64)
                    {
                        this.Core.OnMessage(DependencyWarnings.Win64Component(sourceLineNumbers, componentId));
                    }

                    keyPath = this.ParseProvidesElement(element, PackageType.None, componentId);
                    break;

                default:
                    this.Core.UnexpectedElement(parentElement, element);
                    break;
                }
                break;

            default:
                this.Core.UnexpectedElement(parentElement, element);
                break;
            }

            return(keyPath);
        }
        /// <summary>
        /// Processes a child element of a Component for the Compiler.
        /// </summary>
        /// <param name="sourceLineNumbers">Source line number for the parent element.</param>
        /// <param name="parentElement">Parent element of element to process.</param>
        /// <param name="element">Element to process.</param>
        /// <param name="keyPath">Explicit key path.</param>
        /// <param name="contextValues">Extra information about the context in which this element is being parsed.</param>
        /// <returns>The component key path type if set.</returns>
        public override CompilerExtension.ComponentKeypathType ParseElement(SourceLineNumberCollection sourceLineNumbers, XmlElement parentElement, XmlElement element, ref string keyPath, params string[] contextValues)
        {
            CompilerExtension.ComponentKeypathType keyPathType = CompilerExtension.ComponentKeypathType.None;

            switch (parentElement.LocalName)
            {
            case "Component":
                string componentId = contextValues[0];

                // 64-bit components may cause issues downlevel.
                bool win64 = false;
                Boolean.TryParse(contextValues[2], out win64);

                switch (element.LocalName)
                {
                case "Provides":
                    if (win64)
                    {
                        this.Core.OnMessage(DependencyWarnings.Win64Component(sourceLineNumbers, componentId));
                    }

                    keyPathType = this.ParseProvidesElement(element, PackageType.None, ref keyPath, componentId);
                    break;

                default:
                    this.Core.UnexpectedElement(parentElement, element);
                    break;
                }
                break;

            default:
                this.Core.UnexpectedElement(parentElement, element);
                break;
            }

            return(keyPathType);
        }
        /// <summary>
        /// Processes the Provides element.
        /// </summary>
        /// <param name="node">The XML node for the Provides element.</param>
        /// <param name="packageType">The type of the package being chained into a bundle, or "None" if building an MSI package.</param>
        /// <param name="keyPath">Explicit key path.</param>
        /// <param name="parentId">The identifier of the parent component or package.</param>
        /// <returns>The type of key path if set.</returns>
        private CompilerExtension.ComponentKeypathType ParseProvidesElement(XmlNode node, PackageType packageType, ref string keyPath, string parentId)
        {
            SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);

            CompilerExtension.ComponentKeypathType keyPathType = CompilerExtension.ComponentKeypathType.None;
            string id          = null;
            string key         = null;
            string version     = null;
            string displayName = null;
            int    attributes  = 0;
            int    illegalChar = -1;

            foreach (XmlAttribute attrib in node.Attributes)
            {
                if (0 == attrib.NamespaceURI.Length || attrib.NamespaceURI == this.schema.TargetNamespace)
                {
                    switch (attrib.LocalName)
                    {
                    case "Id":
                        id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
                        break;

                    case "Key":
                        key = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                        break;

                    case "Version":
                        version = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib, true);
                        break;

                    case "DisplayName":
                        displayName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
                        break;

                    default:
                        this.Core.UnexpectedAttribute(sourceLineNumbers, attrib);
                        break;
                    }
                }
                else
                {
                    this.Core.UnsupportedExtensionAttribute(sourceLineNumbers, attrib);
                }
            }

            // Make sure the key is valid. The key will default to the ProductCode for MSI packages
            // and the package code for MSP packages in the binder if not specified.
            if (!String.IsNullOrEmpty(key))
            {
                // Make sure the key does not contain any illegal characters or values.
                if (0 <= (illegalChar = key.IndexOfAny(DependencyCommon.InvalidCharacters)))
                {
                    StringBuilder sb = new StringBuilder(DependencyCommon.InvalidCharacters.Length * 2);
                    Array.ForEach <char>(DependencyCommon.InvalidCharacters, c => sb.Append(c).Append(" "));

                    this.Core.OnMessage(DependencyErrors.IllegalCharactersInProvider(sourceLineNumbers, "Key", key[illegalChar], sb.ToString()));
                }
                else if ("ALL" == key)
                {
                    this.Core.OnMessage(DependencyErrors.ReservedValue(sourceLineNumbers, node.LocalName, "Key", key));
                }
            }
            else if (PackageType.ExePackage == packageType || PackageType.MsuPackage == packageType)
            {
                // Must specify the provider key when authored for a package.
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.LocalName, "Key"));
            }
            else if (PackageType.None == packageType)
            {
                // Make sure the ProductCode is authored and set the key.
                this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "Property", "ProductCode");
                key = "!(bind.property.ProductCode)";
            }

            // The Version attribute should not be authored in or for an MSI package.
            if (!String.IsNullOrEmpty(version))
            {
                switch (packageType)
                {
                case PackageType.None:
                    this.Core.OnMessage(DependencyWarnings.DiscouragedVersionAttribute(sourceLineNumbers));
                    break;

                case PackageType.MsiPackage:
                    this.Core.OnMessage(DependencyWarnings.DiscouragedVersionAttribute(sourceLineNumbers, parentId));
                    break;
                }
            }
            else if (PackageType.MspPackage == packageType || PackageType.MsuPackage == packageType)
            {
                // Must specify the Version when authored for packages that do not contain a version.
                this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.LocalName, "Version"));
            }

            // Need the element ID for child element processing, so generate now if not authored.
            if (String.IsNullOrEmpty(id))
            {
                id = this.Core.GenerateIdentifier("dep", node.LocalName, parentId, key);
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI == this.schema.TargetNamespace)
                    {
                        switch (child.LocalName)
                        {
                        case "Requires":
                            this.ParseRequiresElement(child, id, PackageType.None == packageType);
                            break;

                        case "RequiresRef":
                            this.ParseRequiresRefElement(child, id, PackageType.None == packageType);
                            break;

                        default:
                            this.Core.UnexpectedElement(node, child);
                            break;
                        }
                    }
                    else
                    {
                        this.Core.UnsupportedExtensionElement(node, child);
                    }
                }
            }

            if (!this.Core.EncounteredError)
            {
                // Create the row in the provider table.
                Row row = this.Core.CreateRow(sourceLineNumbers, "WixDependencyProvider");
                row[0] = id;
                row[1] = parentId;
                row[2] = key;

                if (!String.IsNullOrEmpty(version))
                {
                    row[3] = version;
                }

                if (!String.IsNullOrEmpty(displayName))
                {
                    row[4] = displayName;
                }

                if (0 != attributes)
                {
                    row[5] = attributes;
                }

                if (PackageType.None == packageType)
                {
                    // Reference the Check custom action to check for dependencies on the current provider.
                    if (Platform.ARM == this.Core.CurrentPlatform)
                    {
                        // Ensure the ARM version of the CA is referenced.
                        this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CustomAction", "WixDependencyCheck_ARM");
                    }
                    else
                    {
                        // All other supported platforms use x86.
                        this.Core.CreateWixSimpleReferenceRow(sourceLineNumbers, "CustomAction", "WixDependencyCheck");
                    }

                    // Generate registry rows for the provider using binder properties.
                    string keyProvides = String.Concat(DependencyCommon.RegistryRoot, key);

                    row    = this.Core.CreateRow(sourceLineNumbers, "Registry");
                    row[0] = this.Core.GenerateIdentifier("reg", id, "(Default)");
                    row[1] = -1;
                    row[2] = keyProvides;
                    row[3] = null;
                    row[4] = "[ProductCode]";
                    row[5] = parentId;

                    // Use the Version registry value as the key path if not already set.
                    string idVersion = this.Core.GenerateIdentifier("reg", id, "Version");
                    if (String.IsNullOrEmpty(keyPath))
                    {
                        keyPath     = idVersion;
                        keyPathType = CompilerExtension.ComponentKeypathType.Registry;
                    }

                    row    = this.Core.CreateRow(sourceLineNumbers, "Registry");
                    row[0] = idVersion;
                    row[1] = -1;
                    row[2] = keyProvides;
                    row[3] = "Version";
                    row[4] = !String.IsNullOrEmpty(version) ? version : "[ProductVersion]";
                    row[5] = parentId;

                    row    = this.Core.CreateRow(sourceLineNumbers, "Registry");
                    row[0] = this.Core.GenerateIdentifier("reg", id, "DisplayName");
                    row[1] = -1;
                    row[2] = keyProvides;
                    row[3] = "DisplayName";
                    row[4] = !String.IsNullOrEmpty(displayName) ? displayName : "[ProductName]";
                    row[5] = parentId;

                    if (0 != attributes)
                    {
                        row    = this.Core.CreateRow(sourceLineNumbers, "Registry");
                        row[0] = this.Core.GenerateIdentifier("reg", id, "Attributes");
                        row[1] = -1;
                        row[2] = keyProvides;
                        row[3] = "Attributes";
                        row[4] = String.Concat("#", attributes.ToString(CultureInfo.InvariantCulture.NumberFormat));
                        row[5] = parentId;
                    }
                }
            }

            return(keyPathType);
        }