コード例 #1
0
        /// <summary>
        /// Finalize the sequence tables.
        /// </summary>
        /// <param name="tables">The collection of all tables.</param>
        /// <remarks>
        /// Creates the sequence elements.  Occurs during finalization because its
        /// not known if sequences refer to custom actions or dialogs during decompilation.
        /// </remarks>
        private void FinalizeSequenceTables(TableCollection tables)
        {
            // finalize the normal sequence tables
            if (OutputType.Product == this.outputType && !this.treatProductAsModule)
            {
                foreach (SequenceTable sequenceTable in Enum.GetValues(typeof(SequenceTable)))
                {
                    // if suppressing UI elements, skip UI-related sequence tables
                    if (this.suppressUI && ("AdminUISequence" == sequenceTable.ToString() || "InstallUISequence" == sequenceTable.ToString()))
                    {
                        continue;
                    }

                    Table actionsTable = new Table(null, this.tableDefinitions["WixAction"]);
                    Table table = tables[sequenceTable.ToString()];

                    if (null != table)
                    {
                        ArrayList actionRows = new ArrayList();
                        bool needAbsoluteScheduling = this.suppressRelativeActionSequencing;
                        WixActionRowCollection nonSequencedActionRows = new WixActionRowCollection();
                        WixActionRowCollection suppressedRelativeActionRows = new WixActionRowCollection();

                        // create a sorted array of actions in this table
                        foreach (Row row in table.Rows)
                        {
                            WixActionRow actionRow = (WixActionRow)actionsTable.CreateRow(null);

                            actionRow.Action = Convert.ToString(row[0]);

                            if (null != row[1])
                            {
                                actionRow.Condition = Convert.ToString(row[1]);
                            }

                            actionRow.Sequence = Convert.ToInt32(row[2]);

                            actionRow.SequenceTable = sequenceTable;

                            actionRows.Add(actionRow);
                        }
                        actionRows.Sort();

                        for (int i = 0; i < actionRows.Count && !needAbsoluteScheduling; i++)
                        {
                            WixActionRow actionRow = (WixActionRow)actionRows[i];
                            WixActionRow standardActionRow = this.standardActions[actionRow.SequenceTable, actionRow.Action];

                            // create actions for custom actions, dialogs, AppSearch when its moved, and standard actions with non-standard conditions
                            if ("AppSearch" == actionRow.Action || null == standardActionRow || actionRow.Condition != standardActionRow.Condition)
                            {
                                WixActionRow previousActionRow = null;
                                WixActionRow nextActionRow = null;

                                // find the previous action row if there is one
                                if (0 <= i - 1)
                                {
                                    previousActionRow = (WixActionRow)actionRows[i - 1];
                                }

                                // find the next action row if there is one
                                if (actionRows.Count > i + 1)
                                {
                                    nextActionRow = (WixActionRow)actionRows[i + 1];
                                }

                                // the logic for setting the before or after attribute for an action:
                                // 1. If more than one action shares the same sequence number, everything must be absolutely sequenced.
                                // 2. If the next action is a standard action and is 1 sequence number higher, this action occurs before it.
                                // 3. If the previous action is a standard action and is 1 sequence number lower, this action occurs after it.
                                // 4. If this action is not standard and the previous action is 1 sequence number lower and does not occur before this action, this action occurs after it.
                                // 5. If this action is not standard and the previous action does not have the same sequence number and the next action is 1 sequence number higher, this action occurs before it.
                                // 6. If this action is AppSearch and has all standard information, ignore it.
                                // 7. If this action is standard and has a non-standard condition, create the action without any scheduling information.
                                // 8. Everything must be absolutely sequenced.
                                if ((null != previousActionRow && actionRow.Sequence == previousActionRow.Sequence) || (null != nextActionRow && actionRow.Sequence == nextActionRow.Sequence))
                                {
                                    needAbsoluteScheduling = true;
                                }
                                else if (null != nextActionRow && null != this.standardActions[sequenceTable, nextActionRow.Action] && actionRow.Sequence + 1 == nextActionRow.Sequence)
                                {
                                    actionRow.Before = nextActionRow.Action;
                                }
                                else if (null != previousActionRow && null != this.standardActions[sequenceTable, previousActionRow.Action] && actionRow.Sequence - 1 == previousActionRow.Sequence)
                                {
                                    actionRow.After = previousActionRow.Action;
                                }
                                else if (null == standardActionRow && null != previousActionRow && actionRow.Sequence - 1 == previousActionRow.Sequence && previousActionRow.Before != actionRow.Action)
                                {
                                    actionRow.After = previousActionRow.Action;
                                }
                                else if (null == standardActionRow && null != previousActionRow && actionRow.Sequence != previousActionRow.Sequence && null != nextActionRow && actionRow.Sequence + 1 == nextActionRow.Sequence)
                                {
                                    actionRow.Before = nextActionRow.Action;
                                }
                                else if ("AppSearch" == actionRow.Action && null != standardActionRow && actionRow.Sequence == standardActionRow.Sequence && actionRow.Condition == standardActionRow.Condition)
                                {
                                    // ignore an AppSearch row which has the WiX standard sequence and a standard condition
                                }
                                else if (null != standardActionRow && actionRow.Condition != standardActionRow.Condition) // standard actions get their standard sequence numbers
                                {
                                    nonSequencedActionRows.Add(actionRow);
                                }
                                else if (0 < actionRow.Sequence)
                                {
                                    needAbsoluteScheduling = true;
                                }
                            }
                            else
                            {
                                suppressedRelativeActionRows.Add(actionRow);
                            }
                        }

                        // create the actions now that we know if they must be absolutely or relatively scheduled
                        foreach (WixActionRow actionRow in actionRows)
                        {
                            if (needAbsoluteScheduling)
                            {
                                // remove any before/after information to ensure this is absolutely sequenced
                                actionRow.Before = null;
                                actionRow.After = null;
                            }
                            else if (nonSequencedActionRows.Contains(actionRow.SequenceTable, actionRow.Action))
                            {
                                // clear the sequence attribute to ensure this action is scheduled without a sequence number (or before/after)
                                actionRow.Sequence = 0;
                            }
                            else if (suppressedRelativeActionRows.Contains(actionRow.SequenceTable, actionRow.Action))
                            {
                                // skip the suppressed relatively scheduled action rows
                                continue;
                            }

                            // create the action element
                            this.CreateActionElement(actionRow);
                        }
                    }
                }
            }
            else if (OutputType.Module == this.outputType || this.treatProductAsModule) // finalize the Module sequence tables
            {
                foreach (SequenceTable sequenceTable in Enum.GetValues(typeof(SequenceTable)))
                {
                    // if suppressing UI elements, skip UI-related sequence tables
                    if (this.suppressUI && ("AdminUISequence" == sequenceTable.ToString() || "InstallUISequence" == sequenceTable.ToString()))
                    {
                        continue;
                    }

                    Table actionsTable = new Table(null, this.tableDefinitions["WixAction"]);
                    Table table = tables[String.Concat("Module", sequenceTable.ToString())];

                    if (null != table)
                    {
                        foreach (Row row in table.Rows)
                        {
                            WixActionRow actionRow = (WixActionRow)actionsTable.CreateRow(null);

                            actionRow.Action = Convert.ToString(row[0]);

                            if (null != row[1])
                            {
                                actionRow.Sequence = Convert.ToInt32(row[1]);
                            }

                            if (null != row[2] && null != row[3])
                            {
                                switch (Convert.ToInt32(row[3]))
                                {
                                    case 0:
                                        actionRow.Before = Convert.ToString(row[2]);
                                        break;
                                    case 1:
                                        actionRow.After = Convert.ToString(row[2]);
                                        break;
                                    default:
                                        this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[3].Column.Name, row[3]));
                                        break;
                                }
                            }

                            if (null != row[4])
                            {
                                actionRow.Condition = Convert.ToString(row[4]);
                            }

                            actionRow.SequenceTable = sequenceTable;

                            // create action elements for non-standard actions
                            if (null == this.standardActions[actionRow.SequenceTable, actionRow.Action] || null != actionRow.After || null != actionRow.Before)
                            {
                                this.CreateActionElement(actionRow);
                            }
                        }
                    }
                }
            }
        }
コード例 #2
0
ファイル: Linker.cs プロジェクト: zooba/wix3
        /// <summary>
        /// Set sequence numbers for all the actions and create rows in the output object.
        /// </summary>
        /// <param name="actionRows">Collection of actions to schedule.</param>
        /// <param name="suppressActionRows">Collection of actions to suppress.</param>
        private void SequenceActions(RowCollection actionRows, RowCollection suppressActionRows)
        {
            WixActionRowCollection overridableActionRows = new WixActionRowCollection();
            WixActionRowCollection requiredActionRows = new WixActionRowCollection();
            ArrayList scheduledActionRows = new ArrayList();

            // gather the required actions for the output type
            if (OutputType.Product == this.activeOutput.Type)
            {
                // AdminExecuteSequence table
                overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "CostFinalize"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "CostInitialize"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "FileCost"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallAdminPackage"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallFiles"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallFinalize"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallInitialize"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallValidate"]);

                // AdminUISequence table
                overridableActionRows.Add(this.standardActions[SequenceTable.AdminUISequence, "CostFinalize"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.AdminUISequence, "CostInitialize"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.AdminUISequence, "ExecuteAction"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.AdminUISequence, "FileCost"]);

                // AdvtExecuteSequence table
                overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "CostFinalize"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "CostInitialize"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "InstallFinalize"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "InstallInitialize"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "InstallValidate"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "PublishFeatures"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "PublishProduct"]);

                // InstallExecuteSequence table
                overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CostFinalize"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CostInitialize"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "FileCost"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallFinalize"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallInitialize"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallValidate"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "ProcessComponents"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "PublishFeatures"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "PublishProduct"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterProduct"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterUser"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnpublishFeatures"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "ValidateProductID"]);

                // InstallUISequence table
                overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "CostFinalize"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "CostInitialize"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "ExecuteAction"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "FileCost"]);
                overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "ValidateProductID"]);
            }

            // gather the required actions for each table
            foreach (Table table in this.activeOutput.Tables)
            {
                switch (table.Name)
                {
                    case "AppSearch":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "AppSearch"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "AppSearch"], true);
                        break;
                    case "BindImage":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "BindImage"], true);
                        break;
                    case "CCPSearch":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "AppSearch"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CCPSearch"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RMCCPSearch"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "AppSearch"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "CCPSearch"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "RMCCPSearch"], true);
                        break;
                    case "Class":
                        overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "RegisterClassInfo"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterClassInfo"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterClassInfo"], true);
                        break;
                    case "Complus":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterComPlus"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterComPlus"], true);
                        break;
                    case "CreateFolder":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CreateFolders"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveFolders"], true);
                        break;
                    case "DuplicateFile":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "DuplicateFiles"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveDuplicateFiles"], true);
                        break;
                    case "Environment":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "WriteEnvironmentStrings"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveEnvironmentStrings"], true);
                        break;
                    case "Extension":
                        overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "RegisterExtensionInfo"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterExtensionInfo"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterExtensionInfo"], true);
                        break;
                    case "File":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallFiles"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveFiles"], true);
                        break;
                    case "Font":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterFonts"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterFonts"], true);
                        break;
                    case "IniFile":
                    case "RemoveIniFile":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "WriteIniValues"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveIniValues"], true);
                        break;
                    case "IsolatedComponent":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "IsolateComponents"], true);
                        break;
                    case "LaunchCondition":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "LaunchConditions"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "LaunchConditions"], true);
                        break;
                    case "MIME":
                        overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "RegisterMIMEInfo"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterMIMEInfo"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterMIMEInfo"], true);
                        break;
                    case "MoveFile":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MoveFiles"], true);
                        break;
                    case "MsiAssembly":
                        overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "MsiPublishAssemblies"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MsiPublishAssemblies"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MsiUnpublishAssemblies"], true);
                        break;
                    case "MsiServiceConfig":
                    case "MsiServiceConfigFailureActions":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MsiConfigureServices"], true);
                        break;
                    case "ODBCDataSource":
                    case "ODBCTranslator":
                    case "ODBCDriver":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "SetODBCFolders"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallODBC"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveODBC"], true);
                        break;
                    case "ProgId":
                        overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "RegisterProgIdInfo"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterProgIdInfo"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterProgIdInfo"], true);
                        break;
                    case "PublishComponent":
                        overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "PublishComponents"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "PublishComponents"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnpublishComponents"], true);
                        break;
                    case "Registry":
                    case "RemoveRegistry":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "WriteRegistryValues"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveRegistryValues"], true);
                        break;
                    case "RemoveFile":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveFiles"], true);
                        break;
                    case "SelfReg":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "SelfRegModules"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "SelfUnregModules"], true);
                        break;
                    case "ServiceControl":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "StartServices"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "StopServices"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "DeleteServices"], true);
                        break;
                    case "ServiceInstall":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallServices"], true);
                        break;
                    case "Shortcut":
                        overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "CreateShortcuts"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CreateShortcuts"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveShortcuts"], true);
                        break;
                    case "TypeLib":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterTypeLibraries"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterTypeLibraries"], true);
                        break;
                    case "Upgrade":
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "FindRelatedProducts"], true);
                        overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "FindRelatedProducts"], true);
                        // Only add the MigrateFeatureStates action if MigrateFeature attribute is set to yes on at least one UpgradeVersion element.
                        foreach (Row row in table.Rows)
                        {
                            int options = (int)row[4];
                            if (MsiInterop.MsidbUpgradeAttributesMigrateFeatures == (options & MsiInterop.MsidbUpgradeAttributesMigrateFeatures))
                            {
                                overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MigrateFeatureStates"], true);
                                overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "MigrateFeatureStates"], true);
                                break;
                            }
                        }
                        break;
                }
            }

            // index all the action rows (look for collisions)
            foreach (WixActionRow actionRow in actionRows)
            {
                if (actionRow.Overridable) // overridable action
                {
                    WixActionRow collidingActionRow = overridableActionRows[actionRow.SequenceTable, actionRow.Action];

                    if (null != collidingActionRow)
                    {
                        this.OnMessage(WixErrors.OverridableActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
                        if (null != collidingActionRow.SourceLineNumbers)
                        {
                            this.OnMessage(WixErrors.OverridableActionCollision2(collidingActionRow.SourceLineNumbers));
                        }
                    }
                    else
                    {
                        overridableActionRows.Add(actionRow);
                    }
                }
                else // unscheduled/scheduled action
                {
                    // unscheduled action (allowed for certain standard actions)
                    if (null == actionRow.Before && null == actionRow.After && 0 == actionRow.Sequence)
                    {
                        WixActionRow standardAction = this.standardActions[actionRow.SequenceTable, actionRow.Action];

                        if (null != standardAction)
                        {
                            // populate the sequence from the standard action
                            actionRow.Sequence = standardAction.Sequence;
                        }
                        else // not a supported unscheduled action
                        {
                            throw new InvalidOperationException(WixStrings.EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet);
                        }
                    }

                    WixActionRow collidingActionRow = requiredActionRows[actionRow.SequenceTable, actionRow.Action];

                    if (null != collidingActionRow)
                    {
                        this.OnMessage(WixErrors.ActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
                        if (null != collidingActionRow.SourceLineNumbers)
                        {
                            this.OnMessage(WixErrors.ActionCollision2(collidingActionRow.SourceLineNumbers));
                        }
                    }
                    else
                    {
                        requiredActionRows.Add(actionRow.Clone());
                    }
                }
            }

            // add the overridable action rows that are not overridden to the required action rows
            foreach (WixActionRow actionRow in overridableActionRows)
            {
                if (null == requiredActionRows[actionRow.SequenceTable, actionRow.Action])
                {
                    requiredActionRows.Add(actionRow.Clone());
                }
            }

            // suppress the required actions that are overridable
            foreach (Row suppressActionRow in suppressActionRows)
            {
                SequenceTable sequenceTable = (SequenceTable)Enum.Parse(typeof(SequenceTable), (string)suppressActionRow[0]);
                string action = (string)suppressActionRow[1];

                // get the action being suppressed (if it exists)
                WixActionRow requiredActionRow = requiredActionRows[sequenceTable, action];

                // if there is an overridable row 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 (null != requiredActionRow)
                {
                    if (requiredActionRow.Overridable)
                    {
                        this.OnMessage(WixWarnings.SuppressAction(suppressActionRow.SourceLineNumbers, action, sequenceTable.ToString()));
                        if (null != requiredActionRow.SourceLineNumbers)
                        {
                            this.OnMessage(WixWarnings.SuppressAction2(requiredActionRow.SourceLineNumbers));
                        }
                        requiredActionRows.Remove(sequenceTable, action);
                    }
                    else // suppressing a non-overridable action row
                    {
                        this.OnMessage(WixErrors.SuppressNonoverridableAction(suppressActionRow.SourceLineNumbers, sequenceTable.ToString(), action));
                        if (null != requiredActionRow.SourceLineNumbers)
                        {
                            this.OnMessage(WixErrors.SuppressNonoverridableAction2(requiredActionRow.SourceLineNumbers));
                        }
                    }
                }
            }

            // create a copy of the required action rows so that new rows can be added while enumerating
            WixActionRow[] copyOfRequiredActionRows = new WixActionRow[requiredActionRows.Count];
            requiredActionRows.CopyTo(copyOfRequiredActionRows, 0);

            // build up dependency trees of the relatively scheduled actions
            foreach (WixActionRow actionRow in copyOfRequiredActionRows)
            {
                if (0 == actionRow.Sequence)
                {
                    // check for standard actions that don't have a sequence number in a merge module
                    if (OutputType.Module == this.activeOutput.Type && Util.IsStandardAction(actionRow.Action))
                    {
                        this.OnMessage(WixErrors.StandardActionRelativelyScheduledInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
                    }

                    this.SequenceActionRow(actionRow, requiredActionRows);
                }
                else if (OutputType.Module == this.activeOutput.Type && 0 < actionRow.Sequence && !Util.IsStandardAction(actionRow.Action)) // check for custom actions and dialogs that have a sequence number
                {
                    this.OnMessage(WixErrors.CustomActionSequencedInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
                }
            }

            // look for standard actions with sequence restrictions that aren't necessarily scheduled based on the presence of a particular table
            if (requiredActionRows.Contains(SequenceTable.InstallExecuteSequence, "DuplicateFiles") && !requiredActionRows.Contains(SequenceTable.InstallExecuteSequence, "InstallFiles"))
            {
                requiredActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallFiles"], true);
            }

            // schedule actions
            if (OutputType.Module == this.activeOutput.Type)
            {
                // add the action row to the list of scheduled action rows
                scheduledActionRows.AddRange(requiredActionRows);
            }
            else
            {
                // process each sequence table individually
                foreach (SequenceTable sequenceTable in Enum.GetValues(typeof(SequenceTable)))
                {
                    // create a collection of just the action rows in this sequence
                    WixActionRowCollection sequenceActionRows = new WixActionRowCollection();
                    foreach (WixActionRow actionRow in requiredActionRows)
                    {
                        if (sequenceTable == actionRow.SequenceTable)
                        {
                            sequenceActionRows.Add(actionRow);
                        }
                    }

                    // schedule the absolutely scheduled actions (by sorting them by their sequence numbers)
                    ArrayList absoluteActionRows = new ArrayList();
                    foreach (WixActionRow actionRow in sequenceActionRows)
                    {
                        if (0 != actionRow.Sequence)
                        {
                            // look for sequence number collisions
                            foreach (WixActionRow sequenceScheduledActionRow in absoluteActionRows)
                            {
                                if (sequenceScheduledActionRow.Sequence == actionRow.Sequence)
                                {
                                    this.OnMessage(WixWarnings.ActionSequenceCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, sequenceScheduledActionRow.Action, actionRow.Sequence));
                                    if (null != sequenceScheduledActionRow.SourceLineNumbers)
                                    {
                                        this.OnMessage(WixWarnings.ActionSequenceCollision2(sequenceScheduledActionRow.SourceLineNumbers));
                                    }
                                }
                            }

                            absoluteActionRows.Add(actionRow);
                        }
                    }
                    absoluteActionRows.Sort();

                    // schedule the relatively scheduled actions (by resolving the dependency trees)
                    int previousUsedSequence = 0;
                    ArrayList relativeActionRows = new ArrayList();
                    for (int j = 0; j < absoluteActionRows.Count; j++)
                    {
                        WixActionRow absoluteActionRow = (WixActionRow)absoluteActionRows[j];
                        int unusedSequence;

                        // get all the relatively scheduled action rows occuring before this absolutely scheduled action row
                        RowCollection allPreviousActionRows = new RowCollection();
                        absoluteActionRow.GetAllPreviousActionRows(sequenceTable, allPreviousActionRows);

                        // get all the relatively scheduled action rows occuring after this absolutely scheduled action row
                        RowCollection allNextActionRows = new RowCollection();
                        absoluteActionRow.GetAllNextActionRows(sequenceTable, allNextActionRows);

                        // check for relatively scheduled actions occuring before/after a special action (these have a negative sequence number)
                        if (0 > absoluteActionRow.Sequence && (0 < allPreviousActionRows.Count || 0 < allNextActionRows.Count))
                        {
                            // create errors for all the before actions
                            foreach (WixActionRow actionRow in allPreviousActionRows)
                            {
                                this.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action));
                            }

                            // create errors for all the after actions
                            foreach (WixActionRow actionRow in allNextActionRows)
                            {
                                this.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action));
                            }

                            // if there is source line information for the absolutely scheduled action display it
                            if (null != absoluteActionRow.SourceLineNumbers)
                            {
                                this.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction2(absoluteActionRow.SourceLineNumbers));
                            }

                            continue;
                        }

                        // schedule the action rows before this one
                        unusedSequence = absoluteActionRow.Sequence - 1;
                        for (int i = allPreviousActionRows.Count - 1; i >= 0; i--)
                        {
                            WixActionRow relativeActionRow = (WixActionRow)allPreviousActionRows[i];

                            // look for collisions
                            if (unusedSequence == previousUsedSequence)
                            {
                                this.OnMessage(WixErrors.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action));
                                if (null != absoluteActionRow.SourceLineNumbers)
                                {
                                    this.OnMessage(WixErrors.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers));
                                }

                                unusedSequence++;
                            }

                            relativeActionRow.Sequence = unusedSequence;
                            relativeActionRows.Add(relativeActionRow);

                            unusedSequence--;
                        }

                        // determine the next used action sequence number
                        int nextUsedSequence;
                        if (absoluteActionRows.Count > j + 1)
                        {
                            nextUsedSequence = ((WixActionRow)absoluteActionRows[j + 1]).Sequence;
                        }
                        else
                        {
                            nextUsedSequence = short.MaxValue + 1;
                        }

                        // schedule the action rows after this one
                        unusedSequence = absoluteActionRow.Sequence + 1;
                        for (int i = 0; i < allNextActionRows.Count; i++)
                        {
                            WixActionRow relativeActionRow = (WixActionRow)allNextActionRows[i];

                            if (unusedSequence == nextUsedSequence)
                            {
                                this.OnMessage(WixErrors.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action));
                                if (null != absoluteActionRow.SourceLineNumbers)
                                {
                                    this.OnMessage(WixErrors.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers));
                                }

                                unusedSequence--;
                            }

                            relativeActionRow.Sequence = unusedSequence;
                            relativeActionRows.Add(relativeActionRow);

                            unusedSequence++;
                        }

                        // keep track of this sequence number as the previous used sequence number for the next iteration
                        previousUsedSequence = absoluteActionRow.Sequence;
                    }

                    // add the absolutely and relatively scheduled actions to the list of scheduled actions
                    scheduledActionRows.AddRange(absoluteActionRows);
                    scheduledActionRows.AddRange(relativeActionRows);
                }
            }

            // create the action rows for sequences that are not suppressed
            foreach (WixActionRow actionRow in scheduledActionRows)
            {
                // skip actions in suppressed sequences
                if ((this.suppressAdminSequence && (SequenceTable.AdminExecuteSequence == actionRow.SequenceTable || SequenceTable.AdminUISequence == actionRow.SequenceTable)) ||
                    (this.suppressAdvertiseSequence && SequenceTable.AdvtExecuteSequence == actionRow.SequenceTable) ||
                    (this.suppressUISequence && (SequenceTable.AdminUISequence == actionRow.SequenceTable || SequenceTable.InstallUISequence == actionRow.SequenceTable)))
                {
                    continue;
                }

                // get the table definition for the action (and ensure the proper table exists for a module)
                TableDefinition sequenceTableDefinition = null;
                switch (actionRow.SequenceTable)
                {
                    case SequenceTable.AdminExecuteSequence:
                        if (OutputType.Module == this.activeOutput.Type)
                        {
                            this.activeOutput.EnsureTable(this.tableDefinitions["AdminExecuteSequence"]);
                            sequenceTableDefinition = this.tableDefinitions["ModuleAdminExecuteSequence"];
                        }
                        else
                        {
                            sequenceTableDefinition = this.tableDefinitions["AdminExecuteSequence"];
                        }
                        break;
                    case SequenceTable.AdminUISequence:
                        if (OutputType.Module == this.activeOutput.Type)
                        {
                            this.activeOutput.EnsureTable(this.tableDefinitions["AdminUISequence"]);
                            sequenceTableDefinition = this.tableDefinitions["ModuleAdminUISequence"];
                        }
                        else
                        {
                            sequenceTableDefinition = this.tableDefinitions["AdminUISequence"];
                        }
                        break;
                    case SequenceTable.AdvtExecuteSequence:
                        if (OutputType.Module == this.activeOutput.Type)
                        {
                            this.activeOutput.EnsureTable(this.tableDefinitions["AdvtExecuteSequence"]);
                            sequenceTableDefinition = this.tableDefinitions["ModuleAdvtExecuteSequence"];
                        }
                        else
                        {
                            sequenceTableDefinition = this.tableDefinitions["AdvtExecuteSequence"];
                        }
                        break;
                    case SequenceTable.InstallExecuteSequence:
                        if (OutputType.Module == this.activeOutput.Type)
                        {
                            this.activeOutput.EnsureTable(this.tableDefinitions["InstallExecuteSequence"]);
                            sequenceTableDefinition = this.tableDefinitions["ModuleInstallExecuteSequence"];
                        }
                        else
                        {
                            sequenceTableDefinition = this.tableDefinitions["InstallExecuteSequence"];
                        }
                        break;
                    case SequenceTable.InstallUISequence:
                        if (OutputType.Module == this.activeOutput.Type)
                        {
                            this.activeOutput.EnsureTable(this.tableDefinitions["InstallUISequence"]);
                            sequenceTableDefinition = this.tableDefinitions["ModuleInstallUISequence"];
                        }
                        else
                        {
                            sequenceTableDefinition = this.tableDefinitions["InstallUISequence"];
                        }
                        break;
                }

                // create the action sequence row in the output
                Table sequenceTable = this.activeOutput.EnsureTable(sequenceTableDefinition);
                Row row = sequenceTable.CreateRow(actionRow.SourceLineNumbers);
                if (this.sectionIdOnRows)
                {
                    row.SectionId = actionRow.SectionId;
                }

                if (OutputType.Module == this.activeOutput.Type)
                {
                    row[0] = actionRow.Action;
                    if (0 != actionRow.Sequence)
                    {
                        row[1] = actionRow.Sequence;
                    }
                    else
                    {
                        bool after = (null == actionRow.Before);
                        row[2] = after ? actionRow.After : actionRow.Before;
                        row[3] = after ? 1 : 0;
                    }
                    row[4] = actionRow.Condition;
                }
                else
                {
                    row[0] = actionRow.Action;
                    row[1] = actionRow.Condition;
                    row[2] = actionRow.Sequence;
                }
            }
        }