예제 #1
0
        /// <summary>
        /// Constructor for auto media assigner.
        /// </summary>
        /// <param name="output">Output</param>
        /// <param name="core">Binder core.</param>
        /// <param name="filesCompressed">True if files are compressed by default. </param>
        public AutoMediaAssigner(Output output, BinderCore core, bool filesCompressed)
        {
            this.output              = output;
            this.core                = core;
            this.filesCompressed     = filesCompressed;
            this.cabinetNameTemplate = "Cab{0}.cab";

            uncompressedFileRows = new FileRowCollection();
            mediaRows            = new MediaRowCollection();
            cabinets             = new Hashtable();
        }
        /// <summary>
        /// Constructor for auto media assigner.
        /// </summary>
        /// <param name="output">Output</param>
        /// <param name="core">Binder core.</param>
        /// <param name="filesCompressed">True if files are compressed by default. </param>
        public AutoMediaAssigner(Output output, BinderCore core, bool filesCompressed)
        {
            this.output = output;
            this.core = core;
            this.filesCompressed = filesCompressed;
            this.cabinetNameTemplate = "Cab{0}.cab";

            uncompressedFileRows = new FileRowCollection();
            mediaRows = new MediaRowCollection();
            cabinets = new Hashtable();
        }
예제 #3
0
        /// <summary>
        /// Creates a new empty output object.
        /// </summary>
        internal Output()
        {
            this.componentsToFeatures  = new ConnectToFeatureCollection();
            this.modulesToFeatures     = new ConnectToFeatureCollection();
            this.featuresToFeatures    = new ConnectToFeatureCollection();
            this.ignoreModularizations = new IgnoreModularizationCollection();

            this.outputTables              = new OutputTableCollection();
            this.importStreams             = new ImportStreamCollection();
            this.modules                   = new RowCollection();
            this.fileMediaInfoCollection   = new FileMediaInformationCollection();
            this.mediaRows                 = new MediaRowCollection();
            this.suppressAdminSequence     = false;
            this.suppressAdvertiseSequence = false;
            this.suppressUISequence        = false;
        }
예제 #4
0
        /// <summary>
        /// Finalize the File table.
        /// </summary>
        /// <param name="tables">The collection of all tables.</param>
        /// <remarks>
        /// Sets the source, diskId, and assembly information for each file.
        /// </remarks>
        private void FinalizeFileTable(TableCollection tables)
        {
            Table fileTable = tables["File"];
            Table mediaTable = tables["Media"];
            Table msiAssemblyTable = tables["MsiAssembly"];
            Table typeLibTable = tables["TypeLib"];

            MediaRowCollection mediaRows;

            // index the media table by media id
            if (null != mediaTable)
            {
                mediaRows = new MediaRowCollection();
                mediaRows.AddRange(mediaTable.Rows);
            }

            // set the disk identifiers and sources for files
            if (null != fileTable)
            {
                foreach (FileRow fileRow in fileTable.Rows)
                {
                    Wix.File file = (Wix.File)this.core.GetIndexedElement("File", fileRow.File);

                    // Don't bother processing files that are orphaned (and won't show up in the output anyway)
                    if (null != file.ParentElement)
                    {
                        // set the diskid
                        if (null != mediaTable)
                        {
                            foreach (MediaRow mediaRow in mediaTable.Rows)
                            {
                                if (fileRow.Sequence <= mediaRow.LastSequence)
                                {
                                    file.DiskId = Convert.ToString(mediaRow.DiskId);
                                    break;
                                }
                            }
                        }                     

                        // set the source (done here because it requires information from the Directory table)
                        if (OutputType.Module == this.outputType)
                        {
                            file.Source = String.Concat(this.exportFilePath, Path.DirectorySeparatorChar, "File", Path.DirectorySeparatorChar, file.Id, '.', this.modularizationGuid.Substring(1, 36).Replace('-', '_'));
                        }
                        else if (Wix.YesNoDefaultType.yes == file.Compressed || (Wix.YesNoDefaultType.no != file.Compressed && this.compressed))
                        {
                            file.Source = String.Concat(this.exportFilePath, Path.DirectorySeparatorChar, "File", Path.DirectorySeparatorChar, file.Id);
                        }
                        else // uncompressed
                        {
                            string fileName = (null != file.ShortName ? file.ShortName : file.Name);

                            if (!this.shortNames && null != file.Name)
                            {
                                fileName = file.Name;
                            }

                            if (this.compressed) // uncompressed at the root of the source image
                            {
                                file.Source = String.Concat("SourceDir", Path.DirectorySeparatorChar, fileName);
                            }
                            else
                            {
                                string sourcePath = this.GetSourcePath(file);

                                file.Source = Path.Combine(sourcePath, fileName);
                            }
                        }
                    }
                }
            }

            // set the file assemblies and manifests
            if (null != msiAssemblyTable)
            {
                foreach (Row row in msiAssemblyTable.Rows)
                {
                    Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[0]));

                    if (null == component)
                    {
                        this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, "MsiAssembly", row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[0]), "Component"));
                    }
                    else
                    {
                        foreach (Wix.ISchemaElement element in component.Children)
                        {
                            Wix.File file = element as Wix.File;

                            if (null != file && Wix.YesNoType.yes == file.KeyPath)
                            {
                                if (null != row[2])
                                {
                                    file.AssemblyManifest = Convert.ToString(row[2]);
                                }

                                if (null != row[3])
                                {
                                    file.AssemblyApplication = Convert.ToString(row[3]);
                                }

                                if (null == row[4] || 0 == Convert.ToInt32(row[4]))
                                {
                                    file.Assembly = Wix.File.AssemblyType.net;
                                }
                                else
                                {
                                    file.Assembly = Wix.File.AssemblyType.win32;
                                }
                            }
                        }
                    }
                }
            }

            // nest the TypeLib elements
            if (null != typeLibTable)
            {
                foreach (Row row in typeLibTable.Rows)
                {
                    Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[2]));
                    Wix.TypeLib typeLib = (Wix.TypeLib)this.core.GetIndexedElement(row);

                    foreach (Wix.ISchemaElement element in component.Children)
                    {
                        Wix.File file = element as Wix.File;

                        if (null != file && Wix.YesNoType.yes == file.KeyPath)
                        {
                            file.AddChild(typeLib);
                        }
                    }
                }
            }
        }
예제 #5
0
파일: Binder.cs 프로젝트: zooba/wix3
        /// <summary>
        /// Update several msi tables with data contained in files references in the File table.
        /// </summary>
        /// <remarks>
        /// For versioned files, update the file version and language in the File table.  For
        /// unversioned files, add a row to the MsiFileHash table for the file.  For assembly
        /// files, add a row to the MsiAssembly table and add AssemblyName information by adding
        /// MsiAssemblyName rows.
        /// </remarks>
        /// <param name="output">Internal representation of the msi database to operate upon.</param>
        /// <param name="fileRows">The indexed file rows.</param>
        /// <param name="mediaRows">The indexed media rows.</param>
        /// <param name="infoCache">A hashtable to populate with the file information (optional).</param>
        /// <param name="modularizationGuid">The modularization guid (used in case of a merge module).</param>
        private Hashtable UpdateFileInformation(Output output, FileRowCollection fileRows, MediaRowCollection mediaRows, IDictionary<string, string> infoCache, string modularizationGuid)
        {
            // Index for all the fileId's
            // NOTE: When dealing with patches, there is a file table for each transform. In most cases, the data in these rows will be the same, however users of this index need to be aware of this.
            Hashtable fileRowIndex = new Hashtable(fileRows.Count);
            Table mediaTable = output.Tables["Media"];

            // calculate sequence numbers and media disk id layout for all file media information objects
            if (OutputType.Module == output.Type)
            {
                int lastSequence = 0;
                foreach (FileRow fileRow in fileRows)
                {
                    fileRow.Sequence = ++lastSequence;
                    fileRowIndex[fileRow.File] = fileRow;
                }
            }
            else if (null != mediaTable)
            {
                int lastSequence = 0;
                MediaRow mediaRow = null;
                SortedList patchGroups = new SortedList();

                // sequence the non-patch-added files
                foreach (FileRow fileRow in fileRows)
                {
                    fileRowIndex[fileRow.File] = fileRow;
                    if (null == mediaRow)
                    {
                        mediaRow = mediaRows[fileRow.DiskId];
                        if (OutputType.Patch == output.Type)
                        {
                            // patch Media cannot start at zero
                            lastSequence = mediaRow.LastSequence;
                        }
                    }
                    else if (mediaRow.DiskId != fileRow.DiskId)
                    {
                        mediaRow.LastSequence = lastSequence;
                        mediaRow = mediaRows[fileRow.DiskId];
                    }

                    if (0 < fileRow.PatchGroup)
                    {
                        ArrayList patchGroup = (ArrayList)patchGroups[fileRow.PatchGroup];

                        if (null == patchGroup)
                        {
                            patchGroup = new ArrayList();
                            patchGroups.Add(fileRow.PatchGroup, patchGroup);
                        }

                        patchGroup.Add(fileRow);
                    }
                    else
                    {
                        fileRow.Sequence = ++lastSequence;
                    }
                }

                if (null != mediaRow)
                {
                    mediaRow.LastSequence = lastSequence;
                    mediaRow = null;
                }

                // sequence the patch-added files
                foreach (ArrayList patchGroup in patchGroups.Values)
                {
                    foreach (FileRow fileRow in patchGroup)
                    {
                        if (null == mediaRow)
                        {
                            mediaRow = mediaRows[fileRow.DiskId];
                        }
                        else if (mediaRow.DiskId != fileRow.DiskId)
                        {
                            mediaRow.LastSequence = lastSequence;
                            mediaRow = mediaRows[fileRow.DiskId];
                        }

                        fileRow.Sequence = ++lastSequence;
                    }
                }

                if (null != mediaRow)
                {
                    mediaRow.LastSequence = lastSequence;
                }
            }
            else
            {
                foreach (FileRow fileRow in fileRows)
                {
                    fileRowIndex[fileRow.File] = fileRow;
                }
            }

            // no more work to do here if there are no file rows in the file table
            // note that this does not mean there are no files - the files from
            // merge modules are never put in the output's file table
            Table fileTable = output.Tables["File"];
            if (null == fileTable)
            {
                return fileRowIndex;
            }

            // gather information about files that did not come from merge modules
            foreach (FileRow row in fileTable.Rows)
            {
                UpdateFileRow(output, infoCache, modularizationGuid, fileRowIndex, row, false);
            }

            return fileRowIndex;
        }
예제 #6
0
파일: Binder.cs 프로젝트: zooba/wix3
        /// <summary>
        /// Process uncompressed files.
        /// </summary>
        /// <param name="tempDatabaseFile">The temporary database file.</param>
        /// <param name="fileRows">The collection of files to copy into the image.</param>
        /// <param name="fileTransfers">Array of files to be transfered.</param>
        /// <param name="mediaRows">The indexed media rows.</param>
        /// <param name="layoutDirectory">The directory in which the image should be layed out.</param>
        /// <param name="compressed">Flag if source image should be compressed.</param>
        /// <param name="longNamesInImage">Flag if long names should be used.</param>
        private void ProcessUncompressedFiles(string tempDatabaseFile, FileRowCollection fileRows, ArrayList fileTransfers, MediaRowCollection mediaRows, string layoutDirectory, bool compressed, bool longNamesInImage)
        {
            if (0 == fileRows.Count || this.core.EncounteredError)
            {
                return;
            }

            Hashtable directories = new Hashtable();
            using (Database db = new Database(tempDatabaseFile, OpenDatabase.ReadOnly))
            {
                using (View directoryView = db.OpenExecuteView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`"))
                {
                    while (true)
                    {
                        using (Record directoryRecord = directoryView.Fetch())
                        {
                            if (null == directoryRecord)
                            {
                                break;
                            }

                            string sourceName = Installer.GetName(directoryRecord.GetString(3), true, longNamesInImage);

                            directories.Add(directoryRecord.GetString(1), new ResolvedDirectory(directoryRecord.GetString(2), sourceName));
                        }
                    }
                }

                using (View fileView = db.OpenView("SELECT `Directory_`, `FileName` FROM `Component`, `File` WHERE `Component`.`Component`=`File`.`Component_` AND `File`.`File`=?"))
                {
                    using (Record fileQueryRecord = new Record(1))
                    {
                        // for each file in the array of uncompressed files
                        foreach (FileRow fileRow in fileRows)
                        {
                            string relativeFileLayoutPath = null;

                            string mediaLayoutDirectory = this.FileManager.ResolveMedia(mediaRows[fileRow.DiskId], layoutDirectory);

                            // setup up the query record and find the appropriate file in the
                            // previously executed file view
                            fileQueryRecord[1] = fileRow.File;
                            fileView.Execute(fileQueryRecord);

                            using (Record fileRecord = fileView.Fetch())
                            {
                                if (null == fileRecord)
                                {
                                    throw new WixException(WixErrors.FileIdentifierNotFound(fileRow.SourceLineNumbers, fileRow.File));
                                }

                                relativeFileLayoutPath = Binder.GetFileSourcePath(directories, fileRecord[1], fileRecord[2], compressed, longNamesInImage);
                            }

                            // finally put together the base media layout path and the relative file layout path
                            string fileLayoutPath = Path.Combine(mediaLayoutDirectory, relativeFileLayoutPath);
                            FileTransfer transfer;
                            if (FileTransfer.TryCreate(fileRow.Source, fileLayoutPath, false, "File", fileRow.SourceLineNumbers, out transfer))
                            {
                                fileTransfers.Add(transfer);
                            }
                        }
                    }
                }
            }
        }
예제 #7
0
파일: Binder.cs 프로젝트: zooba/wix3
        /// <summary>
        /// Creates cabinet files.
        /// </summary>
        /// <param name="output">Output to generate image for.</param>
        /// <param name="fileRows">The indexed file rows.</param>
        /// <param name="fileTransfers">Array of files to be transfered.</param>
        /// <param name="mediaRows">The indexed media rows.</param>
        /// <param name="layoutDirectory">The directory in which the image should be layed out.</param>
        /// <param name="compressed">Flag if source image should be compressed.</param>
        /// <returns>The uncompressed file rows.</returns>
        private FileRowCollection CreateCabinetFiles(Output output, FileRowCollection fileRows, ArrayList fileTransfers, MediaRowCollection mediaRows, string layoutDirectory, bool compressed, AutoMediaAssigner autoMediaAssigner)
        {
            this.SetCabbingThreadCount();

            // Send Binder object to Facilitate NewCabNamesCallBack Callback
            CabinetBuilder cabinetBuilder = new CabinetBuilder(this.cabbingThreadCount, Marshal.GetFunctionPointerForDelegate(this.newCabNamesCallBack));

            // Supply Compile MediaTemplate Attributes to Cabinet Builder
            int MaximumCabinetSizeForLargeFileSplitting;
            int MaximumUncompressedMediaSize;
            this.GetMediaTemplateAttributes(out MaximumCabinetSizeForLargeFileSplitting, out MaximumUncompressedMediaSize);
            cabinetBuilder.MaximumCabinetSizeForLargeFileSplitting = MaximumCabinetSizeForLargeFileSplitting;
            cabinetBuilder.MaximumUncompressedMediaSize = MaximumUncompressedMediaSize;

            if (null != this.MessageHandler)
            {
                cabinetBuilder.Message += new MessageEventHandler(this.MessageHandler);
            }

            foreach (DictionaryEntry entry in autoMediaAssigner.Cabinets)
            {
                MediaRow mediaRow = (MediaRow)entry.Key;
                FileRowCollection files = (FileRowCollection)entry.Value;

                string cabinetDir = this.FileManager.ResolveMedia(mediaRow, layoutDirectory);

                CabinetWorkItem cabinetWorkItem = this.CreateCabinetWorkItem(output, cabinetDir, mediaRow, files, fileTransfers);
                if (null != cabinetWorkItem)
                {
                    cabinetBuilder.Enqueue(cabinetWorkItem);
                }
            }

            // stop processing if an error previously occurred
            if (this.core.EncounteredError)
            {
                return null;
            }

            // create queued cabinets with multiple threads
            int cabError = cabinetBuilder.CreateQueuedCabinets();
            if (0 != cabError)
            {
                this.core.EncounteredError = true;
                return null;
            }

            return autoMediaAssigner.UncompressedFileRows;
        }
예제 #8
0
파일: Binder.cs 프로젝트: zooba/wix3
        private bool BindDatabase(Output output, string databaseFile)
        {
            foreach (BinderExtension extension in this.extensions)
            {
                extension.DatabaseInitialize(output);
            }

            bool compressed = false;
            FileRowCollection fileRows = new FileRowCollection(OutputType.Patch == output.Type);
            bool longNames = false;
            MediaRowCollection mediaRows = new MediaRowCollection();
            Hashtable suppressModularizationIdentifiers = null;
            StringCollection suppressedTableNames = new StringCollection();
            Table propertyTable = output.Tables["Property"];

            this.WriteBuildInfoTable(output, databaseFile);

            // gather all the wix variables
            Table wixVariableTable = output.Tables["WixVariable"];
            if (null != wixVariableTable)
            {
                foreach (WixVariableRow wixVariableRow in wixVariableTable.Rows)
                {
                    this.WixVariableResolver.AddVariable(wixVariableRow);
                }
            }

            // gather all the suppress modularization identifiers
            Table wixSuppressModularizationTable = output.Tables["WixSuppressModularization"];
            if (null != wixSuppressModularizationTable)
            {
                suppressModularizationIdentifiers = new Hashtable(wixSuppressModularizationTable.Rows.Count);

                foreach (Row row in wixSuppressModularizationTable.Rows)
                {
                    suppressModularizationIdentifiers[row[0]] = null;
                }
            }

            // localize fields, resolve wix variables, and resolve file paths
            Hashtable cabinets = new Hashtable();
            ArrayList delayedFields = new ArrayList();
            this.ResolveFields(output.Tables, cabinets, delayedFields);

            // if there are any fields to resolve later, create the cache to populate during bind
            IDictionary<string, string> variableCache = null;
            if (0 < delayedFields.Count)
            {
                variableCache = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
            }

            this.LocalizeUI(output.Tables);

            // process the summary information table before the other tables
            string modularizationGuid = this.BindDatabaseSummaryInfo(output, out longNames, out compressed);

            // stop processing if an error previously occurred
            if (this.core.EncounteredError)
            {
                return false;
            }

            // modularize identifiers and add tables with real streams to the import tables
            if (OutputType.Module == output.Type)
            {
                foreach (Table table in output.Tables)
                {
                    table.Modularize(modularizationGuid, suppressModularizationIdentifiers);
                }

                // Reset the special property lists after modularization. The linker creates these properties before modularization
                // so we have to reconstruct them for merge modules after modularization in the binder.
                Table wixPropertyTable = output.Tables["WixProperty"];
                if (null != wixPropertyTable)
                {
                    // Create lists of the properties that contribute to the special lists of properties.
                    SortedList adminProperties = new SortedList();
                    SortedList secureProperties = new SortedList();
                    SortedList hiddenProperties = new SortedList();

                    foreach (WixPropertyRow wixPropertyRow in wixPropertyTable.Rows)
                    {
                        if (wixPropertyRow.Admin)
                        {
                            adminProperties[wixPropertyRow.Id] = null;
                        }

                        if (wixPropertyRow.Hidden)
                        {
                            hiddenProperties[wixPropertyRow.Id] = null;
                        }

                        if (wixPropertyRow.Secure)
                        {
                            secureProperties[wixPropertyRow.Id] = null;
                        }
                    }

                    if (0 < adminProperties.Count || 0 < hiddenProperties.Count || 0 < secureProperties.Count)
                    {
                        Table table = output.Tables["Property"];
                        foreach (Row propertyRow in table.Rows)
                        {
                            if ("AdminProperties" == (string)propertyRow[0])
                            {
                                propertyRow[1] = GetPropertyListString(adminProperties);
                            }

                            if ("MsiHiddenProperties" == (string)propertyRow[0])
                            {
                                propertyRow[1] = GetPropertyListString(hiddenProperties);
                            }

                            if ("SecureCustomProperties" == (string)propertyRow[0])
                            {
                                propertyRow[1] = GetPropertyListString(secureProperties);
                            }
                        }
                    }
                }
            }

            // merge unreal table data into the real tables
            // this must occur after all variables and source paths have been resolved
            this.MergeUnrealTables(output.Tables);

            if (this.core.EncounteredError)
            {
                return false;
            }

            if (OutputType.Patch == output.Type)
            {
                foreach (SubStorage substorage in output.SubStorages)
                {
                    Output transform = (Output)substorage.Data;
                    this.ResolveFields(transform.Tables, cabinets, null);
                    this.MergeUnrealTables(transform.Tables);
                }
            }

            // stop processing if an error previously occurred
            if (this.core.EncounteredError)
            {
                return false;
            }

            // index the File table for quicker access later
            // this must occur after the unreal data has been merged in
            Table fileTable = output.Tables["File"];
            if (null != fileTable)
            {
                fileRows.AddRange(fileTable.Rows);
            }

            // stop processing if an error previously occurred
            if (this.core.EncounteredError)
            {
                return false;
            }

            // add binder variables for all properties
            propertyTable = output.Tables["Property"];
            if (null != propertyTable)
            {
                foreach (Row propertyRow in propertyTable.Rows)
                {
                    string property = propertyRow[0].ToString();

                    // set the ProductCode if its generated
                    if (OutputType.Product == output.Type && "ProductCode" == property && "*" == propertyRow[1].ToString())
                    {
                        propertyRow[1] = Common.GenerateGuid();

                        // Update the target ProductCode in any instance transforms
                        foreach (SubStorage subStorage in output.SubStorages)
                        {
                            Output subStorageOutput = (Output)subStorage.Data;
                            if (OutputType.Transform != subStorageOutput.Type)
                            {
                                continue;
                            }

                            Table instanceSummaryInformationTable = subStorageOutput.Tables["_SummaryInformation"];
                            foreach (Row row in instanceSummaryInformationTable.Rows)
                            {
                                if ((int)SummaryInformation.Transform.ProductCodes == (int)row[0])
                                {
                                    row[1] = ((string)row[1]).Replace("*", (string)propertyRow[1]);
                                    break;
                                }
                            }
                        }
                    }

                    // add the property name and value to the variableCache
                    if (0 != delayedFields.Count)
                    {
                        string key = String.Concat("property.", Demodularize(output, modularizationGuid, property));
                        variableCache[key] = (string)propertyRow[1];
                    }
                }
            }

            // extract files that come from cabinet files (this does not extract files from merge modules)
            this.ExtractCabinets(cabinets);

            // retrieve files and their information from merge modules
            if (OutputType.Product == output.Type)
            {
                this.ProcessMergeModules(output, fileRows);
            }
            else if (OutputType.Patch == output.Type)
            {
                // merge transform data into the output object
                this.CopyTransformData(output, fileRows);
            }

            // stop processing if an error previously occurred
            if (this.core.EncounteredError)
            {
                return false;
            }

            // assign files to media
            AutoMediaAssigner autoMediaAssigner = new AutoMediaAssigner(output, this.core, compressed);
            autoMediaAssigner.AssignFiles(fileRows);

            // update file version, hash, assembly, etc.. information
            this.core.OnMessage(WixVerboses.UpdatingFileInformation());
            Hashtable indexedFileRows = this.UpdateFileInformation(output, fileRows, autoMediaAssigner.MediaRows, variableCache, modularizationGuid);

            // set generated component guids
            this.SetComponentGuids(output);

            // With the Component Guids set now we can create instance transforms.
            this.CreateInstanceTransforms(output);

            this.ValidateComponentGuids(output);

            this.UpdateControlText(output);

            if (0 < delayedFields.Count)
            {
                this.ResolveDelayedFields(output, delayedFields, variableCache, modularizationGuid);
            }

            // stop processing if an error previously occurred
            if (this.core.EncounteredError)
            {
                return false;
            }

            // Extended binder extensions can be called now that fields are resolved.
            foreach (BinderExtension extension in this.extensions)
            {
                BinderExtensionEx extensionEx = extension as BinderExtensionEx;
                if (null != extensionEx)
                {
                    output.EnsureTable(this.core.TableDefinitions["WixBindUpdatedFiles"]);
                    extensionEx.DatabaseAfterResolvedFields(output);
                }
            }

            Table updatedFiles = output.Tables["WixBindUpdatedFiles"];
            if (null != updatedFiles)
            {
                foreach (Row updatedFile in updatedFiles.Rows)
                {
                    FileRow updatedFileRow = (FileRow)indexedFileRows[updatedFile[0]];
                    this.UpdateFileRow(output, null, modularizationGuid, indexedFileRows, updatedFileRow, true);
                }
            }

            // stop processing if an error previously occurred
            if (this.core.EncounteredError)
            {
                return false;
            }

            // create cabinet files and process uncompressed files
            string layoutDirectory = Path.GetDirectoryName(databaseFile);
            FileRowCollection uncompressedFileRows = null;
            if (!this.suppressLayout || OutputType.Module == output.Type)
            {
                this.core.OnMessage(WixVerboses.CreatingCabinetFiles());
                uncompressedFileRows = this.CreateCabinetFiles(output, fileRows, this.fileTransfers, autoMediaAssigner.MediaRows, layoutDirectory, compressed, autoMediaAssigner);
            }

            if (OutputType.Patch == output.Type)
            {
                // copy output data back into the transforms
                this.CopyTransformData(output, null);
            }

            // stop processing if an error previously occurred
            if (this.core.EncounteredError)
            {
                return false;
            }

            // add back suppressed tables which must be present prior to merging in modules
            if (OutputType.Product == output.Type)
            {
                Table wixMergeTable = output.Tables["WixMerge"];

                if (null != wixMergeTable && 0 < wixMergeTable.Rows.Count)
                {
                    foreach (SequenceTable sequence in Enum.GetValues(typeof(SequenceTable)))
                    {
                        string sequenceTableName = sequence.ToString();
                        Table sequenceTable = output.Tables[sequenceTableName];

                        if (null == sequenceTable)
                        {
                            sequenceTable = output.EnsureTable(this.core.TableDefinitions[sequenceTableName]);
                        }

                        if (0 == sequenceTable.Rows.Count)
                        {
                            suppressedTableNames.Add(sequenceTableName);
                        }
                    }
                }
            }

            foreach (BinderExtension extension in this.extensions)
            {
                extension.DatabaseFinalize(output);
            }

            // generate database file
            this.core.OnMessage(WixVerboses.GeneratingDatabase());
            string tempDatabaseFile = Path.Combine(this.TempFilesLocation, Path.GetFileName(databaseFile));
            this.GenerateDatabase(output, tempDatabaseFile, false, false);

            FileTransfer transfer;
            if (FileTransfer.TryCreate(tempDatabaseFile, databaseFile, true, output.Type.ToString(), null, out transfer)) // note where this database needs to move in the future
            {
                transfer.Built = true;
                this.fileTransfers.Add(transfer);
            }

            // stop processing if an error previously occurred
            if (this.core.EncounteredError)
            {
                return false;
            }

            // Output the output to a file
            if (null != this.pdbFile)
            {
                Pdb pdb = new Pdb(null);
                pdb.Output = output;
                pdb.Save(this.pdbFile, null, this.WixVariableResolver, this.TempFilesLocation);
            }

            // merge modules
            if (OutputType.Product == output.Type)
            {
                this.core.OnMessage(WixVerboses.MergingModules());
                this.MergeModules(tempDatabaseFile, output, fileRows, suppressedTableNames);

                // stop processing if an error previously occurred
                if (this.core.EncounteredError)
                {
                    return false;
                }
            }

            // inspect the MSI prior to running ICEs
            InspectorCore inspectorCore = new InspectorCore(this.MessageHandler);
            foreach (InspectorExtension inspectorExtension in this.inspectorExtensions)
            {
                inspectorExtension.Core = inspectorCore;
                inspectorExtension.InspectDatabase(tempDatabaseFile, output);

                // reset
                inspectorExtension.Core = null;
            }

            if (inspectorCore.EncounteredError)
            {
                return false;
            }

            // validate the output if there is an MSI validator
            if (null != this.validator)
            {
                Stopwatch stopwatch = Stopwatch.StartNew();

                // set the output file for source line information
                this.validator.Output = output;

                this.core.OnMessage(WixVerboses.ValidatingDatabase());
                this.core.EncounteredError = !this.validator.Validate(tempDatabaseFile);

                stopwatch.Stop();
                this.core.OnMessage(WixVerboses.ValidatedDatabase(stopwatch.ElapsedMilliseconds));

                // stop processing if an error previously occurred
                if (this.core.EncounteredError)
                {
                    return false;
                }
            }

            // process uncompressed files
            if (!this.suppressLayout)
            {
                this.ProcessUncompressedFiles(tempDatabaseFile, uncompressedFileRows, this.fileTransfers, autoMediaAssigner.MediaRows, layoutDirectory, compressed, longNames);
            }

            // layout media
            try
            {
                this.core.OnMessage(WixVerboses.LayingOutMedia());
                this.LayoutMedia(this.fileTransfers, this.suppressAclReset);
            }
            finally
            {
                if (!String.IsNullOrEmpty(this.contentsFile))
                {
                    this.CreateContentsFile(this.contentsFile, fileRows);
                }

                if (!String.IsNullOrEmpty(this.outputsFile))
                {
                    this.CreateOutputsFile(this.outputsFile, this.fileTransfers, this.pdbFile);
                }

                if (!String.IsNullOrEmpty(this.builtOutputsFile))
                {
                    this.CreateBuiltOutputsFile(this.builtOutputsFile, this.fileTransfers, this.pdbFile);
                }
            }

            return !this.core.EncounteredError;
        }
예제 #9
0
        /// <summary>
        /// Creates a new empty output object.
        /// </summary>
        internal Output()
        {
            this.componentsToFeatures = new ConnectToFeatureCollection();
            this.modulesToFeatures = new ConnectToFeatureCollection();
            this.featuresToFeatures = new ConnectToFeatureCollection();
            this.ignoreModularizations = new IgnoreModularizationCollection();

            this.outputTables = new OutputTableCollection();
            this.importStreams = new ImportStreamCollection();
            this.modules = new RowCollection();
            this.fileMediaInfoCollection = new FileMediaInformationCollection();
            this.mediaRows = new MediaRowCollection();
            this.suppressAdminSequence = false;
            this.suppressAdvertiseSequence = false;
            this.suppressUISequence = false;
        }