Beispiel #1
0
        private void SchedulePropertyExeAction(IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier name, string source, string cmdline, CustomActionSymbol caTemplate, string condition, string beforeAction, string afterAction)
        {
            const SequenceTable sequence = SequenceTable.InstallExecuteSequence;

            caTemplate.SourceType = CustomActionSourceType.Property;
            caTemplate.Source     = source;
            caTemplate.TargetType = CustomActionTargetType.Exe;
            caTemplate.Target     = cmdline;
            section.AddSymbol(caTemplate);

            section.AddSymbol(new WixActionSymbol(sourceLineNumbers, new Identifier(name.Access, sequence, name.Id))
            {
                SequenceTable = SequenceTable.InstallExecuteSequence,
                Action        = name.Id,
                Condition     = condition,
                // no explicit sequence
                Before      = beforeAction,
                After       = afterAction,
                Overridable = false,
            });

            if (null != beforeAction)
            {
                if (WindowsInstallerStandard.IsStandardAction(beforeAction))
                {
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixAction, sequence.ToString(), beforeAction);
                }
                else
                {
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.CustomAction, beforeAction);
                }
            }

            if (null != afterAction)
            {
                if (WindowsInstallerStandard.IsStandardAction(afterAction))
                {
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixAction, sequence.ToString(), afterAction);
                }
                else
                {
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.CustomAction, afterAction);
                }
            }
        }
        private void SchedulePropertyExeAction(IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier name, string source, string cmdline, int extraBits, string condition, string beforeAction, string afterAction)
        {
            const string sequence = "InstallExecuteSequence";

            var actionRow = this.ParseHelper.CreateRow(section, sourceLineNumbers, "CustomAction", name);

            actionRow.Set(1, VSCompiler.MsidbCustomActionTypeProperty | VSCompiler.MsidbCustomActionTypeExe | extraBits);
            actionRow.Set(2, source);
            actionRow.Set(3, cmdline);

            var sequenceRow = this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixAction", new Identifier(name.Access, sequence, name.Id));

            sequenceRow.Set(0, sequence);
            sequenceRow.Set(1, name.Id);
            sequenceRow.Set(2, condition);
            // no explicit sequence
            sequenceRow.Set(4, beforeAction);
            sequenceRow.Set(5, afterAction);
            sequenceRow.Set(6, 0); // not overridable

            if (null != beforeAction)
            {
                if (WindowsInstallerStandard.IsStandardAction(beforeAction))
                {
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "WixAction", sequence, beforeAction);
                }
                else
                {
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", beforeAction);
                }
            }

            if (null != afterAction)
            {
                if (WindowsInstallerStandard.IsStandardAction(afterAction))
                {
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "WixAction", sequence, afterAction);
                }
                else
                {
                    this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", afterAction);
                }
            }
        }
        private void SchedulePropertyExeAction(SourceLineNumber sourceLineNumbers, Identifier name, string source, string cmdline, int extraBits, string condition, string beforeAction, string afterAction)
        {
            const string sequence = "InstallExecuteSequence";

            Row actionRow = this.Core.CreateRow(sourceLineNumbers, "CustomAction", name);

            actionRow[1] = VSCompiler.MsidbCustomActionTypeProperty | VSCompiler.MsidbCustomActionTypeExe | extraBits;
            actionRow[2] = source;
            actionRow[3] = cmdline;

            Row sequenceRow = this.Core.CreateRow(sourceLineNumbers, "WixAction");

            sequenceRow[0] = sequence;
            sequenceRow[1] = name.Id;
            sequenceRow[2] = condition;
            // no explicit sequence
            sequenceRow[4] = beforeAction;
            sequenceRow[5] = afterAction;
            sequenceRow[6] = 0; // not overridable

            if (null != beforeAction)
            {
                if (WindowsInstallerStandard.IsStandardAction(beforeAction))
                {
                    this.Core.CreateSimpleReference(sourceLineNumbers, "WixAction", sequence, beforeAction);
                }
                else
                {
                    this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", beforeAction);
                }
            }

            if (null != afterAction)
            {
                if (WindowsInstallerStandard.IsStandardAction(afterAction))
                {
                    this.Core.CreateSimpleReference(sourceLineNumbers, "WixAction", sequence, afterAction);
                }
                else
                {
                    this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", afterAction);
                }
            }
        }
Beispiel #4
0
        public WixActionSymbol ScheduleActionSymbol(IntermediateSection section, SourceLineNumber sourceLineNumbers, AccessModifier access, SequenceTable sequence, string actionName, string condition, string beforeAction, string afterAction, bool overridable = false)
        {
            var actionId = new Identifier(access, sequence, actionName);

            var actionSymbol = section.AddSymbol(new WixActionSymbol(sourceLineNumbers, actionId)
            {
                SequenceTable = sequence,
                Action        = actionName,
                Condition     = condition,
                Before        = beforeAction,
                After         = afterAction,
                Overridable   = overridable,
            });

            if (null != beforeAction)
            {
                if (WindowsInstallerStandard.IsStandardAction(beforeAction))
                {
                    this.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixAction, sequence.ToString(), beforeAction);
                }
                else
                {
                    this.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.CustomAction, beforeAction);
                }
            }

            if (null != afterAction)
            {
                if (WindowsInstallerStandard.IsStandardAction(afterAction))
                {
                    this.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixAction, sequence.ToString(), afterAction);
                }
                else
                {
                    this.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.CustomAction, afterAction);
                }
            }

            return(actionSymbol);
        }
        public void Execute()
        {
            var requiredActionSymbols = new Dictionary <string, WixActionSymbol>();

            // Get the standard actions required based on symbols in the section.
            var overridableActionSymbols = this.GetRequiredStandardActions();

            // Index all the action symbols and look for collisions.
            foreach (var actionSymbol in this.Section.Symbols.OfType <WixActionSymbol>())
            {
                if (actionSymbol.Overridable) // overridable action
                {
                    if (overridableActionSymbols.TryGetValue(actionSymbol.Id.Id, out var collidingActionSymbol))
                    {
                        this.Messaging.Write(ErrorMessages.OverridableActionCollision(actionSymbol.SourceLineNumbers, actionSymbol.SequenceTable.ToString(), actionSymbol.Action));
                        if (null != collidingActionSymbol.SourceLineNumbers)
                        {
                            this.Messaging.Write(ErrorMessages.OverridableActionCollision2(collidingActionSymbol.SourceLineNumbers));
                        }
                    }
                    else
                    {
                        overridableActionSymbols.Add(actionSymbol.Id.Id, actionSymbol);
                    }
                }
                else // unsequenced or sequenced action.
                {
                    // Unsequenced action (allowed for certain standard actions).
                    if (null == actionSymbol.Before && null == actionSymbol.After && !actionSymbol.Sequence.HasValue)
                    {
                        if (WindowsInstallerStandard.TryGetStandardAction(actionSymbol.Id.Id, out var standardAction))
                        {
                            // Populate the sequence from the standard action
                            actionSymbol.Sequence = standardAction.Sequence;
                        }
                        else // not a supported unscheduled action.
                        {
                            throw new InvalidOperationException("Found an action with no Sequence, Before, or After column set.");
                        }
                    }

                    if (requiredActionSymbols.TryGetValue(actionSymbol.Id.Id, out var collidingActionSymbol))
                    {
                        this.Messaging.Write(ErrorMessages.ActionCollision(actionSymbol.SourceLineNumbers, actionSymbol.SequenceTable.ToString(), actionSymbol.Action));
                        if (null != collidingActionSymbol.SourceLineNumbers)
                        {
                            this.Messaging.Write(ErrorMessages.ActionCollision2(collidingActionSymbol.SourceLineNumbers));
                        }
                    }
                    else
                    {
                        requiredActionSymbols.Add(actionSymbol.Id.Id, actionSymbol);
                    }
                }
            }

            // Add the overridable action symbols that are not overridden to the required action symbols.
            foreach (var actionSymbol in overridableActionSymbols.Values)
            {
                if (!requiredActionSymbols.ContainsKey(actionSymbol.Id.Id))
                {
                    requiredActionSymbols.Add(actionSymbol.Id.Id, actionSymbol);
                }
            }

            // Suppress the required actions that are overridable.
            foreach (var suppressActionSymbol in this.Section.Symbols.OfType <WixSuppressActionSymbol>())
            {
                var key = suppressActionSymbol.Id.Id;

                // If there is an overridable symbol to suppress; suppress it. There is no warning if there
                // is no action to suppress because the action may be suppressed from a merge module in
                // the binder.
                if (requiredActionSymbols.TryGetValue(key, out var requiredActionSymbol))
                {
                    if (requiredActionSymbol.Overridable)
                    {
                        this.Messaging.Write(WarningMessages.SuppressAction(suppressActionSymbol.SourceLineNumbers, suppressActionSymbol.Action, suppressActionSymbol.SequenceTable.ToString()));
                        if (null != requiredActionSymbol.SourceLineNumbers)
                        {
                            this.Messaging.Write(WarningMessages.SuppressAction2(requiredActionSymbol.SourceLineNumbers));
                        }

                        requiredActionSymbols.Remove(key);
                    }
                    else // suppressing a non-overridable action symbol
                    {
                        this.Messaging.Write(ErrorMessages.SuppressNonoverridableAction(suppressActionSymbol.SourceLineNumbers, suppressActionSymbol.SequenceTable.ToString(), suppressActionSymbol.Action));
                        if (null != requiredActionSymbol.SourceLineNumbers)
                        {
                            this.Messaging.Write(ErrorMessages.SuppressNonoverridableAction2(requiredActionSymbol.SourceLineNumbers));
                        }
                    }
                }
            }

            // Build up dependency trees of the relatively scheduled actions.
            // Use ToList() to create a copy of the required action symbols so that new symbols can
            // be added while enumerating.
            foreach (var actionSymbol in requiredActionSymbols.Values.ToList())
            {
                if (!actionSymbol.Sequence.HasValue)
                {
                    // check for standard actions that don't have a sequence number in a merge module
                    if (SectionType.Module == this.Section.Type && WindowsInstallerStandard.IsStandardAction(actionSymbol.Action))
                    {
                        this.Messaging.Write(ErrorMessages.StandardActionRelativelyScheduledInModule(actionSymbol.SourceLineNumbers, actionSymbol.SequenceTable.ToString(), actionSymbol.Action));
                    }

                    this.SequenceActionSymbol(actionSymbol, requiredActionSymbols);
                }
                else if (SectionType.Module == this.Section.Type && 0 < actionSymbol.Sequence && !WindowsInstallerStandard.IsStandardAction(actionSymbol.Action)) // check for custom actions and dialogs that have a sequence number
                {
                    this.Messaging.Write(ErrorMessages.CustomActionSequencedInModule(actionSymbol.SourceLineNumbers, actionSymbol.SequenceTable.ToString(), actionSymbol.Action));
                }
            }

            // Look for standard actions with sequence restrictions that aren't necessarily scheduled based
            // on the presence of a particular table.
            if (requiredActionSymbols.ContainsKey("InstallExecuteSequence/DuplicateFiles") && !requiredActionSymbols.ContainsKey("InstallExecuteSequence/InstallFiles"))
            {
                WindowsInstallerStandard.TryGetStandardAction("InstallExecuteSequence/InstallFiles", out var standardAction);
                requiredActionSymbols.Add(standardAction.Id.Id, standardAction);
            }

            // Schedule actions.
            List <WixActionSymbol> scheduledActionSymbols;

            if (SectionType.Module == this.Section.Type)
            {
                scheduledActionSymbols = requiredActionSymbols.Values.ToList();
            }
            else
            {
                scheduledActionSymbols = this.ScheduleActions(requiredActionSymbols);
            }

            // Remove all existing WixActionSymbols from the section then add the
            // scheduled actions back to the section. Note: we add the indices in
            // reverse order to make it easy to remove them from the list later.
            var removeIndices = new List <int>();

            for (var i = this.Section.Symbols.Count - 1; i >= 0; --i)
            {
                var symbol = this.Section.Symbols[i];
                if (symbol.Definition.Type == SymbolDefinitionType.WixAction)
                {
                    removeIndices.Add(i);
                }
            }

            foreach (var removeIndex in removeIndices)
            {
                this.Section.Symbols.RemoveAt(removeIndex);
            }

            foreach (var action in scheduledActionSymbols)
            {
                this.Section.AddSymbol(action);
            }
        }
Beispiel #6
0
        private string ModularizedRowFieldValue(Row row, Field field)
        {
            var fieldData = field.AsString();

            if (!(WindowsInstallerStandard.IsStandardAction(fieldData) || WindowsInstallerStandard.IsStandardProperty(fieldData)))
            {
                var modularizeType = field.Column.ModularizeType;

                // special logic for the ControlEvent table's Argument column
                // this column requires different modularization methods depending upon the value of the Event column
                if (ColumnModularizeType.ControlEventArgument == field.Column.ModularizeType)
                {
                    switch (row[2].ToString())
                    {
                    case "CheckExistingTargetPath": // redirectable property name
                    case "CheckTargetPath":
                    case "DoAction":                // custom action name
                    case "NewDialog":               // dialog name
                    case "SelectionBrowse":
                    case "SetTargetPath":
                    case "SpawnDialog":
                    case "SpawnWaitDialog":
                        if (Common.IsIdentifier(fieldData))
                        {
                            modularizeType = ColumnModularizeType.Column;
                        }
                        else
                        {
                            modularizeType = ColumnModularizeType.Property;
                        }
                        break;

                    default:     // formatted
                        modularizeType = ColumnModularizeType.Property;
                        break;
                    }
                }
                else if (ColumnModularizeType.ControlText == field.Column.ModularizeType)
                {
                    // icons are stored in the Binary table, so they get column-type modularization
                    if (("Bitmap" == row[2].ToString() || "Icon" == row[2].ToString()) && Common.IsIdentifier(fieldData))
                    {
                        modularizeType = ColumnModularizeType.Column;
                    }
                    else
                    {
                        modularizeType = ColumnModularizeType.Property;
                    }
                }

                switch (modularizeType)
                {
                case ColumnModularizeType.Column:
                    // ensure the value is an identifier (otherwise it shouldn't be modularized this way)
                    if (!Common.IsIdentifier(fieldData))
                    {
                        throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixDataStrings.EXP_CannotModularizeIllegalID, fieldData));
                    }

                    // if we're not supposed to suppress modularization of this identifier
                    if (!this.SuppressModularizationIdentifiers.Contains(fieldData))
                    {
                        fieldData = String.Concat(fieldData, ".", this.ModularizationGuid);
                    }
                    break;

                case ColumnModularizeType.Property:
                case ColumnModularizeType.Condition:
                    Regex regex;
                    if (ColumnModularizeType.Property == modularizeType)
                    {
                        regex = new Regex(@"\[(?<identifier>[#$!]?[a-zA-Z_][a-zA-Z0-9_\.]*)]", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
                    }
                    else
                    {
                        Debug.Assert(ColumnModularizeType.Condition == modularizeType);

                        // This heinous looking regular expression is actually quite an elegant way
                        // to shred the entire condition into the identifiers that need to be
                        // modularized.  Let's break it down piece by piece:
                        //
                        // 1. Look for the operators: NOT, EQV, XOR, OR, AND, IMP (plus a space).  Note that the
                        //    regular expression is case insensitive so we don't have to worry about
                        //    all the permutations of these strings.
                        // 2. Look for quoted strings.  Quoted strings are just text and are ignored
                        //    outright.
                        // 3. Look for environment variables.  These look like identifiers we might
                        //    otherwise be interested in but start with a percent sign.  Like quoted
                        //    strings these enviroment variable references are ignored outright.
                        // 4. Match all identifiers that are things that need to be modularized.  Note
                        //    the special characters (!, $, ?, &) that denote Component and Feature states.
                        regex = new Regex(@"NOT\s|EQV\s|XOR\s|OR\s|AND\s|IMP\s|"".*?""|%[a-zA-Z_][a-zA-Z0-9_\.]*|(?<identifier>[!$\?&]?[a-zA-Z_][a-zA-Z0-9_\.]*)", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);

                        // less performant version of the above with captures showing where everything lives
                        // regex = new Regex(@"(?<operator>NOT|EQV|XOR|OR|AND|IMP)|(?<string>"".*?"")|(?<environment>%[a-zA-Z_][a-zA-Z0-9_\.]*)|(?<identifier>[!$\?&]?[a-zA-Z_][a-zA-Z0-9_\.]*)",RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
                    }

                    var matches = regex.Matches(fieldData);

                    var sb = new StringBuilder(fieldData);

                    // Notice how this code walks backward through the list
                    // because it modifies the string as we through it.
                    for (var i = matches.Count - 1; 0 <= i; i--)
                    {
                        var group = matches[i].Groups["identifier"];
                        if (group.Success)
                        {
                            var identifier = group.Value;
                            if (!WindowsInstallerStandard.IsStandardProperty(identifier) && !this.SuppressModularizationIdentifiers.Contains(identifier))
                            {
                                sb.Insert(group.Index + group.Length, '.');
                                sb.Insert(group.Index + group.Length + 1, this.ModularizationGuid);
                            }
                        }
                    }

                    fieldData = sb.ToString();
                    break;

                case ColumnModularizeType.CompanionFile:
                    // if we're not supposed to ignore this identifier and the value does not start with
                    // a digit, we must have a companion file so modularize it
                    if (!this.SuppressModularizationIdentifiers.Contains(fieldData) &&
                        0 < fieldData.Length && !Char.IsDigit(fieldData, 0))
                    {
                        fieldData = String.Concat(fieldData, ".", this.ModularizationGuid);
                    }
                    break;

                case ColumnModularizeType.Icon:
                    if (!this.SuppressModularizationIdentifiers.Contains(fieldData))
                    {
                        var start = fieldData.LastIndexOf(".", StringComparison.Ordinal);
                        if (-1 == start)
                        {
                            fieldData = String.Concat(fieldData, ".", this.ModularizationGuid);
                        }
                        else
                        {
                            fieldData = String.Concat(fieldData.Substring(0, start), ".", this.ModularizationGuid, fieldData.Substring(start));
                        }
                    }
                    break;

                case ColumnModularizeType.SemicolonDelimited:
                    var keys = fieldData.Split(';');
                    for (var i = 0; i < keys.Length; ++i)
                    {
                        if (!String.IsNullOrEmpty(keys[i]))
                        {
                            keys[i] = String.Concat(keys[i], ".", this.ModularizationGuid);
                        }
                    }

                    fieldData = String.Join(";", keys);
                    break;
                }
            }

            return(fieldData);
        }