예제 #1
0
        /// <param name="output">Output to generate image for.</param>
        /// <param name="fileTransfers">Array of files to be transfered.</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>
        public void Execute()
        {
            RowDictionary <WixMediaRow> wixMediaRows = new RowDictionary <WixMediaRow>(this.WixMediaTable);

            this.lastCabinetAddedToMediaTable = new Dictionary <string, string>();

            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;

            foreach (var entry in this.FileRowsByCabinet)
            {
                MediaRow mediaRow = entry.Key;
                IEnumerable <FileFacade> files            = entry.Value;
                CompressionLevel         compressionLevel = this.DefaultCompressionLevel;

                WixMediaRow wixMediaRow       = null;
                string      mediaLayoutFolder = null;

                if (wixMediaRows.TryGetValue(mediaRow.GetKey(), out wixMediaRow))
                {
                    mediaLayoutFolder = wixMediaRow.Layout;

                    if (wixMediaRow.CompressionLevel.HasValue)
                    {
                        compressionLevel = wixMediaRow.CompressionLevel.Value;
                    }
                }

                string cabinetDir = this.ResolveMedia(mediaRow, mediaLayoutFolder, this.LayoutDirectory);

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

            // stop processing if an error previously occurred
            if (Messaging.Instance.EncounteredError)
            {
                return;
            }

            // create queued cabinets with multiple threads
            cabinetBuilder.CreateQueuedCabinets();
            if (Messaging.Instance.EncounteredError)
            {
                return;
            }
        }
예제 #2
0
        public void WhenTryingToGetAValueAndTheKeyExistsShould()
        {
            //Arrange
            var key                         = 01;
            var expectedValue               = "expectedValue";
            var comparer                    = Comparer <int> .Default;
            var mockEqualityService         = MockRepository.GenerateMock <IComparer <Cell <int, string> > >();
            var mockEqualityServiceProvider = MockRepository.GenerateMock <IEqualityServiceProvider <int> >();

            mockEqualityServiceProvider.Stub(x => x.GetKeyComparer(comparer)).Return(comparer);
            mockEqualityService
            .Stub(s => s.Compare(
                      Arg <Cell <int, string> > .Matches(x => x.Key == key),
                      Arg <Cell <int, string> > .Matches(x => x.Key == key)))
            .Return(0);
            var sut = new RowDictionary <int, string>(comparer, mockEqualityServiceProvider);

            sut.Add(key, expectedValue);
            string resultValue;

            //Act
            var resultBooleanValue = sut.TryGetValue(key, out resultValue);

            //Assert
            Assert.That(resultBooleanValue, Is.True);
            Assert.That(resultValue, Is.EqualTo(expectedValue));
        }
예제 #3
0
        public void WhenTryingToGetAValueAndTheKeyDoesNotExistShould()
        {
            //Arrange
            var key = "key";
            var thisKeyDoesNotExist         = "thisKeyDoesNotExist";
            var expectedValue               = "expectedValue";
            var comparer                    = (IComparer <string>)StringComparer.InvariantCultureIgnoreCase;
            var mockEqualityService         = MockRepository.GenerateMock <IComparer <Cell <string, string> > >();
            var mockEqualityServiceProvider = MockRepository.GenerateMock <IEqualityServiceProvider <string> >();

            mockEqualityServiceProvider.Stub(x => x.GetKeyComparer(comparer)).Return(comparer);
            mockEqualityService
            .Stub(s => s.Compare(
                      Arg <Cell <string, string> > .Matches(x => x.Key == key),
                      Arg <Cell <string, string> > .Matches(x => x.Key == thisKeyDoesNotExist)))
            .Return(-1);

            var sut = new RowDictionary <string, string>(comparer, mockEqualityServiceProvider);

            sut.Add(key, expectedValue);
            string resultValue;

            //Act
            var resultBooleanValue = sut.TryGetValue(thisKeyDoesNotExist, out resultValue);

            //Assert
            Assert.That(resultBooleanValue, Is.False);
        }
예제 #4
0
        public void ShouldBeAbleToAddANewValueAndRetriveTheSameValueUsingTheSameKey()
        {
            //Arrange
            var key           = "key";
            var expectedValue = "Hola mundo";
            var sut           = new RowDictionary <string, string>();

            sut.Add(key, expectedValue);
            string result;

            //Act
            sut.TryGetValue(key, out result);

            //Assert
            Assert.That(result, Is.EqualTo(expectedValue));
        }
예제 #5
0
        public void ShouldBeAbleToRetrieveTheValueUsingTheKeyWhenThereIsOnlyOneValueInserted()
        {
            //Arrange
            var key           = 01;
            var expectedValue = "expectedValue";
            var sut           = new RowDictionary <int, string>();

            sut.Add(key, expectedValue);
            string result;

            //Act
            sut.TryGetValue(key, out result);

            //Assert
            Assert.That(result, Is.EqualTo(expectedValue));
        }
예제 #6
0
        public void ShouldBeAbleToRetrieveTheValueUsingTheKeyWhenTheKeyIsNonPrimitive()
        {
            //Arrange
            var          myKey = new { FirstName = "ABC", LastName = "DFG" };
            const string whenTheKeyIsAnObject = "WhenTheKeyIsAnObject";
            var          sut = new RowDictionary <object, string>();

            sut.Add(myKey, whenTheKeyIsAnObject);
            string result;

            //Act
            sut.TryGetValue(myKey, out result);

            //Assert
            Assert.That(result, Is.EqualTo(whenTheKeyIsAnObject));
        }
예제 #7
0
        public void Execute()
        {
            List <FileFacade> facades = new List <FileFacade>(this.FileTable.Rows.Count);

            RowDictionary <WixFileRow>           wixFiles        = new RowDictionary <WixFileRow>(this.WixFileTable);
            RowDictionary <WixDeltaPatchFileRow> deltaPatchFiles = new RowDictionary <WixDeltaPatchFileRow>(this.WixDeltaPatchFileTable);

            foreach (FileRow file in this.FileTable.Rows)
            {
                WixDeltaPatchFileRow deltaPatchFile = null;

                deltaPatchFiles.TryGetValue(file.File, out deltaPatchFile);

                facades.Add(new FileFacade(file, wixFiles[file.File], deltaPatchFile));
            }

            if (null != this.WixDeltaPatchSymbolPathsTable)
            {
                this.ResolveDeltaPatchSymbolPaths(deltaPatchFiles, facades);
            }

            this.FileFacades = facades;
        }
예제 #8
0
        /// <summary>
        /// Assign files to cabinets based on Media authoring.
        /// </summary>
        /// <param name="mediaTable"></param>
        /// <param name="mergeModuleMediaRow"></param>
        /// <param name="fileFacades"></param>
        private void ManuallyAssignFiles(Table mediaTable, MediaRow mergeModuleMediaRow, IEnumerable <FileFacade> fileFacades, Dictionary <MediaRow, List <FileFacade> > filesByCabinetMedia, RowDictionary <MediaRow> mediaRows, List <FileFacade> uncompressedFiles)
        {
            if (OutputType.Module != this.Output.Type)
            {
                if (null != mediaTable)
                {
                    Dictionary <string, MediaRow> cabinetMediaRows = new Dictionary <string, MediaRow>(StringComparer.InvariantCultureIgnoreCase);
                    foreach (MediaRow mediaRow in mediaTable.Rows)
                    {
                        // If the Media row has a cabinet, make sure it is unique across all Media rows.
                        if (!String.IsNullOrEmpty(mediaRow.Cabinet))
                        {
                            MediaRow existingRow;
                            if (cabinetMediaRows.TryGetValue(mediaRow.Cabinet, out existingRow))
                            {
                                Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName(mediaRow.SourceLineNumbers, mediaRow.Cabinet));
                                Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName2(existingRow.SourceLineNumbers, existingRow.Cabinet));
                            }
                            else
                            {
                                cabinetMediaRows.Add(mediaRow.Cabinet, mediaRow);
                            }
                        }

                        mediaRows.Add(mediaRow);
                    }
                }

                foreach (MediaRow mediaRow in mediaRows.Values)
                {
                    if (null != mediaRow.Cabinet)
                    {
                        filesByCabinetMedia.Add(mediaRow, new List <FileFacade>());
                    }
                }
            }

            foreach (FileFacade facade in fileFacades)
            {
                if (OutputType.Module == this.Output.Type)
                {
                    filesByCabinetMedia[mergeModuleMediaRow].Add(facade);
                }
                else
                {
                    MediaRow mediaRow;
                    if (!mediaRows.TryGetValue(facade.WixFile.DiskId.ToString(CultureInfo.InvariantCulture), out mediaRow))
                    {
                        Messaging.Instance.OnMessage(WixErrors.MissingMedia(facade.File.SourceLineNumbers, facade.WixFile.DiskId));
                        continue;
                    }

                    // When building a product, if the current file is not to be compressed or if
                    // the package set not to be compressed, don't cab it.
                    if (OutputType.Product == this.Output.Type &&
                        (YesNoType.No == facade.File.Compressed ||
                         (YesNoType.NotSet == facade.File.Compressed && !this.FilesCompressed)))
                    {
                        uncompressedFiles.Add(facade);
                    }
                    else // file is marked compressed.
                    {
                        List <FileFacade> cabinetFiles;
                        if (filesByCabinetMedia.TryGetValue(mediaRow, out cabinetFiles))
                        {
                            cabinetFiles.Add(facade);
                        }
                        else
                        {
                            Messaging.Instance.OnMessage(WixErrors.ExpectedMediaCabinet(facade.File.SourceLineNumbers, facade.File.File, facade.WixFile.DiskId));
                        }
                    }
                }
            }
        }
예제 #9
0
        public void Execute()
        {
            List <FileTransfer> fileTransfers = new List <FileTransfer>();

            Hashtable directories = new Hashtable();

            RowDictionary <WixMediaRow> wixMediaRows = new RowDictionary <WixMediaRow>(this.WixMediaTable);

            using (Database db = new Database(this.DatabasePath, 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, this.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 (FileFacade facade in this.FileFacades)
                        {
                            MediaRow mediaRow = this.MediaRows.Get(facade.WixFile.DiskId);
                            string   relativeFileLayoutPath = null;

                            WixMediaRow wixMediaRow       = null;
                            string      mediaLayoutFolder = null;

                            if (wixMediaRows.TryGetValue(mediaRow.GetKey(), out wixMediaRow))
                            {
                                mediaLayoutFolder = wixMediaRow.Layout;
                            }

                            string mediaLayoutDirectory = this.ResolveMedia(mediaRow, mediaLayoutFolder, this.LayoutDirectory);

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

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

                                relativeFileLayoutPath = Binder.GetFileSourcePath(directories, fileRecord[1], fileRecord[2], this.Compressed, this.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(facade.WixFile.Source, fileLayoutPath, false, "File", facade.File.SourceLineNumbers, out transfer))
                            {
                                fileTransfers.Add(transfer);
                            }
                        }
                    }
                }
            }

            this.FileTransfers = fileTransfers;
        }
예제 #10
0
        public void Execute()
        {
            var fileFacadesByDiskId = new Dictionary <int, Dictionary <string, FileFacade> >();

            // Index patch file facades by diskId+fileId.
            foreach (var facade in this.FileFacades)
            {
                if (!fileFacadesByDiskId.TryGetValue(facade.DiskId, out var mediaFacades))
                {
                    mediaFacades = new Dictionary <string, FileFacade>();
                    fileFacadesByDiskId.Add(facade.DiskId, mediaFacades);
                }

                mediaFacades.Add(facade.Id, facade);
            }

            var patchMediaRows = new RowDictionary <MediaRow>(this.Output.Tables["Media"]);

            // Index paired transforms by name without the "#" prefix.
            var pairedTransforms = this.SubStorages.Where(s => s.Name.StartsWith("#")).ToDictionary(s => s.Name, s => s.Data);

            // Copy File bind data into substorages
            foreach (var substorage in this.SubStorages.Where(s => !s.Name.StartsWith("#")))
            {
                var mainTransform = substorage.Data;

                var mainMsiFileHashIndex = new RowDictionary <Row>(mainTransform.Tables["MsiFileHash"]);

                var pairedTransform = pairedTransforms["#" + substorage.Name];

                // Copy Media.LastSequence.
                var pairedMediaTable = pairedTransform.Tables["Media"];
                foreach (MediaRow pairedMediaRow in pairedMediaTable.Rows)
                {
                    var patchMediaRow = patchMediaRows.Get(pairedMediaRow.DiskId);
                    pairedMediaRow.LastSequence = patchMediaRow.LastSequence;
                }

                // Validate file row changes for keypath-related issues
                this.ValidateFileRowChanges(mainTransform);

                // Index File table of pairedTransform
                var pairedFileRows = new RowDictionary <FileRow>(pairedTransform.Tables["File"]);

                var mainFileTable = mainTransform.Tables["File"];
                if (null != mainFileTable)
                {
                    // Remove the MsiFileHash table because it will be updated later with the final file hash for each file
                    mainTransform.Tables.Remove("MsiFileHash");

                    foreach (FileRow mainFileRow in mainFileTable.Rows)
                    {
                        if (RowOperation.Delete == mainFileRow.Operation)
                        {
                            continue;
                        }
                        else if (RowOperation.None == mainFileRow.Operation)
                        {
                            continue;
                        }

                        // Index patch files by diskId+fileId
                        if (!fileFacadesByDiskId.TryGetValue(mainFileRow.DiskId, out var mediaFacades))
                        {
                            mediaFacades = new Dictionary <string, FileFacade>();
                            fileFacadesByDiskId.Add(mainFileRow.DiskId, mediaFacades);
                        }

                        // copy data from the patch back to the transform
                        if (mediaFacades.TryGetValue(mainFileRow.File, out var facade))
                        {
                            var patchFileRow  = facade.GetFileRow();
                            var pairedFileRow = pairedFileRows.Get(mainFileRow.File);

                            for (var i = 0; i < patchFileRow.Fields.Length; i++)
                            {
                                var patchValue = patchFileRow.FieldAsString(i) ?? String.Empty;
                                var mainValue  = mainFileRow.FieldAsString(i) ?? String.Empty;

                                if (1 == i)
                                {
                                    // File.Component_ changes should not come from the shared file rows
                                    // that contain the file information as each individual transform might
                                    // have different changes (or no changes at all).
                                }
                                else if (6 == i) // File.Attributes should not changed for binary deltas
                                {
#if TODO_PATCHING_DELTA
                                    if (null != patchFileRow.Patch)
                                    {
                                        // File.Attribute should not change for binary deltas
                                        pairedFileRow.Attributes       = mainFileRow.Attributes;
                                        mainFileRow.Fields[i].Modified = false;
                                    }
#endif
                                }
                                else if (7 == i) // File.Sequence is updated in pairedTransform, not mainTransform
                                {
                                    // file sequence is updated in Patch table instead of File table for delta patches
#if TODO_PATCHING_DELTA
                                    if (null != patchFileRow.Patch)
                                    {
                                        pairedFileRow.Fields[i].Modified = false;
                                    }
                                    else
#endif
                                    {
                                        pairedFileRow[i] = patchFileRow[i];
                                        pairedFileRow.Fields[i].Modified = true;
                                    }
                                    mainFileRow.Fields[i].Modified = false;
                                }
                                else if (patchValue != mainValue)
                                {
                                    mainFileRow[i] = patchFileRow[i];
                                    mainFileRow.Fields[i].Modified = true;
                                    if (mainFileRow.Operation == RowOperation.None)
                                    {
                                        mainFileRow.Operation = RowOperation.Modify;
                                    }
                                }
                            }

                            // Copy MsiFileHash row for this File.
                            if (!mainMsiFileHashIndex.TryGetValue(patchFileRow.File, out var patchHashRow))
                            {
                                //patchHashRow = patchFileRow.Hash;
                                throw new NotImplementedException();
                            }

                            if (null != patchHashRow)
                            {
                                var mainHashTable = mainTransform.EnsureTable(this.TableDefinitions["MsiFileHash"]);
                                var mainHashRow   = mainHashTable.CreateRow(mainFileRow.SourceLineNumbers);
                                for (var i = 0; i < patchHashRow.Fields.Length; i++)
                                {
                                    mainHashRow[i] = patchHashRow[i];
                                    if (i > 1)
                                    {
                                        // assume all hash fields have been modified
                                        mainHashRow.Fields[i].Modified = true;
                                    }
                                }

                                // assume the MsiFileHash operation follows the File one
                                mainHashRow.Operation = mainFileRow.Operation;
                            }

                            // copy MsiAssemblyName rows for this File
#if TODO_PATCHING
                            List <Row> patchAssemblyNameRows = patchFileRow.AssemblyNames;
                            if (null != patchAssemblyNameRows)
                            {
                                var mainAssemblyNameTable = mainTransform.EnsureTable(this.TableDefinitions["MsiAssemblyName"]);
                                foreach (var patchAssemblyNameRow in patchAssemblyNameRows)
                                {
                                    // Copy if there isn't an identical modified/added row already in the transform.
                                    var foundMatchingModifiedRow = false;
                                    foreach (var mainAssemblyNameRow in mainAssemblyNameTable.Rows)
                                    {
                                        if (RowOperation.None != mainAssemblyNameRow.Operation && mainAssemblyNameRow.GetPrimaryKey('/').Equals(patchAssemblyNameRow.GetPrimaryKey('/')))
                                        {
                                            foundMatchingModifiedRow = true;
                                            break;
                                        }
                                    }

                                    if (!foundMatchingModifiedRow)
                                    {
                                        var mainAssemblyNameRow = mainAssemblyNameTable.CreateRow(mainFileRow.SourceLineNumbers);
                                        for (var i = 0; i < patchAssemblyNameRow.Fields.Length; i++)
                                        {
                                            mainAssemblyNameRow[i] = patchAssemblyNameRow[i];
                                        }

                                        // assume value field has been modified
                                        mainAssemblyNameRow.Fields[2].Modified = true;
                                        mainAssemblyNameRow.Operation          = mainFileRow.Operation;
                                    }
                                }
                            }
#endif

                            // Add patch header for this file
#if TODO_PATCHING_DELTA
                            if (null != patchFileRow.Patch)
                            {
                                // Add the PatchFiles action automatically to the AdminExecuteSequence and InstallExecuteSequence tables.
                                this.AddPatchFilesActionToSequenceTable(SequenceTable.AdminExecuteSequence, mainTransform, pairedTransform, mainFileRow);
                                this.AddPatchFilesActionToSequenceTable(SequenceTable.InstallExecuteSequence, mainTransform, pairedTransform, mainFileRow);

                                // Add to Patch table
                                var patchTable = pairedTransform.EnsureTable(this.TableDefinitions["Patch"]);
                                if (0 == patchTable.Rows.Count)
                                {
                                    patchTable.Operation = TableOperation.Add;
                                }

                                var patchRow = patchTable.CreateRow(mainFileRow.SourceLineNumbers);
                                patchRow[0] = patchFileRow.File;
                                patchRow[1] = patchFileRow.Sequence;

                                var patchFile = new FileInfo(patchFileRow.Source);
                                patchRow[2] = (int)patchFile.Length;
                                patchRow[3] = 0 == (PatchAttributeType.AllowIgnoreOnError & patchFileRow.PatchAttributes) ? 0 : 1;

                                var streamName = patchTable.Name + "." + patchRow[0] + "." + patchRow[1];
                                if (Msi.MsiInterop.MsiMaxStreamNameLength < streamName.Length)
                                {
                                    streamName = "_" + Guid.NewGuid().ToString("D").ToUpperInvariant().Replace('-', '_');

                                    var patchHeadersTable = pairedTransform.EnsureTable(this.TableDefinitions["MsiPatchHeaders"]);
                                    if (0 == patchHeadersTable.Rows.Count)
                                    {
                                        patchHeadersTable.Operation = TableOperation.Add;
                                    }

                                    var patchHeadersRow = patchHeadersTable.CreateRow(mainFileRow.SourceLineNumbers);
                                    patchHeadersRow[0]        = streamName;
                                    patchHeadersRow[1]        = patchFileRow.Patch;
                                    patchRow[5]               = streamName;
                                    patchHeadersRow.Operation = RowOperation.Add;
                                }
                                else
                                {
                                    patchRow[4] = patchFileRow.Patch;
                                }
                                patchRow.Operation = RowOperation.Add;
                            }
#endif
                        }
                        else
                        {
                            // TODO: throw because all transform rows should have made it into the patch
                        }
                    }
                }

                this.Output.Tables.Remove("Media");
                this.Output.Tables.Remove("File");
                this.Output.Tables.Remove("MsiFileHash");
                this.Output.Tables.Remove("MsiAssemblyName");
            }
        }