Ejemplo n.º 1
0
        /// <summary>
        /// Processes the ProviderKey bundle attribute.
        /// </summary>
        /// <param name="sourceLineNumbers">Source line number for the parent element.</param>
        /// <param name="parentElement">Parent element of attribute.</param>
        /// <param name="attribute">The XML attribute for the ProviderKey attribute.</param>
        private void ParseProviderKeyAttribute(IntermediateSection section, SourceLineNumber sourceLineNumbers, XElement parentElement, XAttribute attribute)
        {
            Identifier id          = null;
            string     providerKey = null;
            int        illegalChar = -1;

            switch (attribute.Name.LocalName)
            {
            case "ProviderKey":
                providerKey = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attribute);
                break;

            default:
                this.ParseHelper.UnexpectedAttribute(parentElement, attribute);
                break;
            }

            // Make sure the key does not contain any illegal characters or values.
            if (String.IsNullOrEmpty(providerKey))
            {
                this.Messaging.Write(ErrorMessages.IllegalEmptyAttributeValue(sourceLineNumbers, parentElement.Name.LocalName, attribute.Name.LocalName));
            }
            else if (0 <= (illegalChar = providerKey.IndexOfAny(DependencyCommon.InvalidCharacters)))
            {
                var sb = new StringBuilder(DependencyCommon.InvalidCharacters.Length * 2);
                Array.ForEach <char>(DependencyCommon.InvalidCharacters, c => sb.Append(c).Append(" "));

                this.Messaging.Write(DependencyErrors.IllegalCharactersInProvider(sourceLineNumbers, "ProviderKey", providerKey[illegalChar], sb.ToString()));
            }
            else if ("ALL" == providerKey)
            {
                this.Messaging.Write(DependencyErrors.ReservedValue(sourceLineNumbers, parentElement.Name.LocalName, "ProviderKey", providerKey));
            }

            // Generate the primary key for the row.
            id = this.ParseHelper.CreateIdentifier("dep", attribute.Name.LocalName, providerKey);

            if (!this.Messaging.EncounteredError)
            {
                // Create the provider symbol for the bundle. The Component_ field is required
                // in the table definition but unused for bundles, so just set it to the valid ID.
                section.AddSymbol(new WixDependencyProviderSymbol(sourceLineNumbers, id)
                {
                    ComponentRef = id.Id,
                    ProviderKey  = providerKey,
                    Attributes   = WixDependencyProviderAttributes.ProvidesAttributesBundle,
                });
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Processes the Requires element.
        /// </summary>
        /// <param name="node">The XML node for the Requires element.</param>
        /// <param name="providerId">The parent provider identifier.</param>
        /// <param name="requiresAction">Whether the Requires custom action should be referenced.</param>
        private void ParseRequiresElement(Intermediate intermediate, IntermediateSection section, XElement node, string providerId, bool requiresAction)
        {
            var        sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(node);
            Identifier id          = null;
            string     providerKey = null;
            string     minVersion  = null;
            string     maxVersion  = null;
            int        attributes  = 0;
            int        illegalChar = -1;

            foreach (var attrib in node.Attributes())
            {
                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
                {
                    switch (attrib.Name.LocalName)
                    {
                    case "Id":
                        id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
                        break;

                    case "ProviderKey":
                        providerKey = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
                        break;

                    case "Minimum":
                        minVersion = this.ParseHelper.GetAttributeVersionValue(sourceLineNumbers, attrib);
                        break;

                    case "Maximum":
                        maxVersion = this.ParseHelper.GetAttributeVersionValue(sourceLineNumbers, attrib);
                        break;

                    case "IncludeMinimum":
                        if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                        {
                            attributes |= DependencyCommon.RequiresAttributesMinVersionInclusive;
                        }
                        break;

                    case "IncludeMaximum":
                        if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
                        {
                            attributes |= DependencyCommon.RequiresAttributesMaxVersionInclusive;
                        }
                        break;

                    default:
                        this.ParseHelper.UnexpectedAttribute(node, attrib);
                        break;
                    }
                }
                else
                {
                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, node, attrib);
                }
            }

            this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, node);

            if (null == id)
            {
                // Generate an ID only if this element is authored under a Provides element; otherwise, a RequiresRef
                // element will be necessary and the Id attribute will be required.
                if (!String.IsNullOrEmpty(providerId))
                {
                    id = this.ParseHelper.CreateIdentifier("dep", node.Name.LocalName, providerKey);
                }
                else
                {
                    this.Messaging.Write(ErrorMessages.ExpectedAttributeWhenElementNotUnderElement(sourceLineNumbers, node.Name.LocalName, "Id", "Provides"));
                    id = Identifier.Invalid;
                }
            }

            if (String.IsNullOrEmpty(providerKey))
            {
                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "ProviderKey"));
            }
            // Make sure the key does not contain any illegal characters.
            else if (0 <= (illegalChar = providerKey.IndexOfAny(DependencyCommon.InvalidCharacters)))
            {
                var sb = new StringBuilder(DependencyCommon.InvalidCharacters.Length * 2);
                Array.ForEach <char>(DependencyCommon.InvalidCharacters, c => sb.Append(c).Append(" "));

                this.Messaging.Write(DependencyErrors.IllegalCharactersInProvider(sourceLineNumbers, "ProviderKey", providerKey[illegalChar], sb.ToString()));
            }

            if (!this.Messaging.EncounteredError)
            {
                // Reference the Require custom action if required.
                if (requiresAction)
                {
                    this.AddReferenceToWixDependencyRequire(section, sourceLineNumbers);
                }

                var symbol = section.AddSymbol(new WixDependencySymbol(sourceLineNumbers, id)
                {
                    ProviderKey = providerKey,
                    MinVersion  = minVersion,
                    MaxVersion  = maxVersion,
                });

                if (0 != attributes)
                {
                    symbol.Attributes = attributes;
                }

                // Create the relationship between this WixDependency symbol and the WixDependencyProvider symbol.
                if (!String.IsNullOrEmpty(providerId))
                {
                    section.AddSymbol(new WixDependencyRefSymbol(sourceLineNumbers)
                    {
                        WixDependencyProviderRef = providerId,
                        WixDependencyRef         = id.Id,
                    });
                }
            }
        }
Ejemplo n.º 3
0
        /// <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 IComponentKeyPath ParseProvidesElement(Intermediate intermediate, IntermediateSection section, XElement node, PackageType packageType, string parentId)
        {
            var sourceLineNumbers         = this.ParseHelper.GetSourceLineNumbers(node);
            IComponentKeyPath keyPath     = null;
            Identifier        id          = null;
            string            key         = null;
            string            version     = null;
            string            displayName = null;
            int illegalChar = -1;

            foreach (var attrib in node.Attributes())
            {
                if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
                {
                    switch (attrib.Name.LocalName)
                    {
                    case "Id":
                        id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
                        break;

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

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

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

                    default:
                        this.ParseHelper.UnexpectedAttribute(node, attrib);
                        break;
                    }
                }
                else
                {
                    this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, node, 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)))
                {
                    var sb = new StringBuilder(DependencyCommon.InvalidCharacters.Length * 2);
                    Array.ForEach <char>(DependencyCommon.InvalidCharacters, c => sb.Append(c).Append(" "));

                    this.Messaging.Write(DependencyErrors.IllegalCharactersInProvider(sourceLineNumbers, "Key", key[illegalChar], sb.ToString()));
                }
                else if ("ALL" == key)
                {
                    this.Messaging.Write(DependencyErrors.ReservedValue(sourceLineNumbers, node.Name.LocalName, "Key", key));
                }
            }
            else if (PackageType.ExePackage == packageType || PackageType.MsuPackage == packageType)
            {
                // Must specify the provider key when authored for a package.
                this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Key"));
            }
            else if (PackageType.None == packageType)
            {
                // Make sure the ProductCode is authored and set the key.
                this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.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.Messaging.Write(DependencyWarnings.DiscouragedVersionAttribute(sourceLineNumbers));
                    break;

                case PackageType.MsiPackage:
                    this.Messaging.Write(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.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Version"));
            }

            // Need the element ID for child element processing, so generate now if not authored.
            if (null == id)
            {
                id = this.ParseHelper.CreateIdentifier("dep", node.Name.LocalName, parentId, key);
            }

            foreach (var child in node.Elements())
            {
                if (this.Namespace == child.Name.Namespace)
                {
                    switch (child.Name.LocalName)
                    {
                    case "Requires":
                        this.ParseRequiresElement(intermediate, section, child, id.Id, PackageType.None == packageType);
                        break;

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

                    default:
                        this.ParseHelper.UnexpectedElement(node, child);
                        break;
                    }
                }
                else
                {
                    this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, node, child);
                }
            }

            if (!this.Messaging.EncounteredError)
            {
                var symbol = section.AddSymbol(new WixDependencyProviderSymbol(sourceLineNumbers, id)
                {
                    ComponentRef = parentId,
                    ProviderKey  = key,
                });

                if (!String.IsNullOrEmpty(version))
                {
                    symbol.Version = version;
                }

                if (!String.IsNullOrEmpty(displayName))
                {
                    symbol.DisplayName = displayName;
                }

                if (PackageType.None == packageType)
                {
                    this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "DependencyCheck", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);

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

                    var value = "[ProductCode]";
                    this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, root, keyProvides, null, value, parentId, false);

                    value = !String.IsNullOrEmpty(version) ? version : "[ProductVersion]";
                    var versionRegistrySymbol =
                        this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, root, keyProvides, "Version", value, parentId, false);

                    value = !String.IsNullOrEmpty(displayName) ? displayName : "[ProductName]";
                    this.ParseHelper.CreateRegistrySymbol(section, sourceLineNumbers, root, keyProvides, "DisplayName", value, parentId, false);

                    // Use the Version registry value and use that as a potential key path.
                    keyPath          = this.CreateComponentKeyPath();
                    keyPath.Id       = versionRegistrySymbol.Id;
                    keyPath.Explicit = false;
                    keyPath.Type     = PossibleKeyPathType.Registry;
                }
            }

            return(keyPath);
        }