/// <summary> /// Assign files to cabinets based on Media authoring. /// </summary> /// <param name="mediaTable"></param> /// <param name="mergeModuleMediaRow"></param> /// <param name="fileRows"></param> private void ManuallyAssignFiles(Table mediaTable, MediaRow mergeModuleMediaRow, FileRowCollection fileRows) { 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)) { this.core.OnMessage(WixErrors.DuplicateCabinetName(mediaRow.SourceLineNumbers, mediaRow.Cabinet)); this.core.OnMessage(WixErrors.DuplicateCabinetName2(existingRow.SourceLineNumbers, existingRow.Cabinet)); } else { cabinetMediaRows.Add(mediaRow.Cabinet, mediaRow); } } this.mediaRows.Add(mediaRow); } } foreach (MediaRow mediaRow in this.mediaRows) { if (null != mediaRow.Cabinet) { this.cabinets.Add(mediaRow, new FileRowCollection()); } } } foreach (FileRow fileRow in fileRows) { if (OutputType.Module == output.Type) { ((FileRowCollection)this.cabinets[mergeModuleMediaRow]).Add(fileRow); } else { MediaRow mediaRow = this.mediaRows[fileRow.DiskId]; // 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 == output.Type && (YesNoType.No == fileRow.Compressed || (YesNoType.NotSet == fileRow.Compressed && !this.filesCompressed))) { uncompressedFileRows.Add(fileRow); } else // file in a Module or marked compressed { FileRowCollection cabinetFileRow = (FileRowCollection)this.cabinets[mediaRow]; if (null != cabinetFileRow) { cabinetFileRow.Add(fileRow); } else { this.core.OnMessage(WixErrors.ExpectedMediaCabinet(fileRow.SourceLineNumbers, fileRow.File, fileRow.DiskId)); } } } } }
/// <summary> /// Assign files to cabinets based on MediaTemplate authoring. /// </summary> /// <param name="fileRows">FileRowCollection</param> private void AutoAssignFiles(Table mediaTable, FileRowCollection fileRows) { const int MaxCabIndex = 999; ulong currentPreCabSize = 0; ulong maxPreCabSizeInBytes; int maxPreCabSizeInMB = 0; int currentCabIndex = 0; MediaRow currentMediaRow = null; Table mediaTemplateTable = this.output.Tables["WixMediaTemplate"]; // Auto assign files to cabinets based on maximum uncompressed media size mediaTable.Rows.Clear(); WixMediaTemplateRow mediaTemplateRow = (WixMediaTemplateRow)mediaTemplateTable.Rows[0]; if (!String.IsNullOrEmpty(mediaTemplateRow.CabinetTemplate)) { this.cabinetNameTemplate = mediaTemplateRow.CabinetTemplate; } string mumsString = Environment.GetEnvironmentVariable("WIX_MUMS"); try { // Override authored mums value if environment variable is authored. if (!String.IsNullOrEmpty(mumsString)) { maxPreCabSizeInMB = Int32.Parse(mumsString); } else { maxPreCabSizeInMB = mediaTemplateRow.MaximumUncompressedMediaSize; } maxPreCabSizeInBytes = (ulong)maxPreCabSizeInMB * 1024 * 1024; } catch (FormatException) { throw new WixException(WixErrors.IllegalEnvironmentVariable("WIX_MUMS", mumsString)); } catch (OverflowException) { throw new WixException(WixErrors.MaximumUncompressedMediaSizeTooLarge(null, maxPreCabSizeInMB)); } foreach (FileRow fileRow in fileRows) { // 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 == output.Type && (YesNoType.No == fileRow.Compressed || (YesNoType.NotSet == fileRow.Compressed && !this.filesCompressed))) { uncompressedFileRows.Add(fileRow); continue; } FileInfo fileInfo = null; // Get the file size try { fileInfo = new FileInfo(fileRow.Source); } catch (ArgumentException) { this.core.OnMessage(WixErrors.InvalidFileName(fileRow.SourceLineNumbers, fileRow.Source)); } catch (PathTooLongException) { this.core.OnMessage(WixErrors.InvalidFileName(fileRow.SourceLineNumbers, fileRow.Source)); } catch (NotSupportedException) { this.core.OnMessage(WixErrors.InvalidFileName(fileRow.SourceLineNumbers, fileRow.Source)); } if (fileInfo.Exists) { if (fileInfo.Length > Int32.MaxValue) { throw new WixException(WixErrors.FileTooLarge(fileRow.SourceLineNumbers, fileRow.Source)); } fileRow.FileSize = Convert.ToInt32(fileInfo.Length, CultureInfo.InvariantCulture); } if (currentCabIndex == MaxCabIndex) { // Associate current file with last cab (irrespective of the size) and cab index is not incremented anymore. FileRowCollection cabinetFileRow = (FileRowCollection)this.cabinets[currentMediaRow]; fileRow.DiskId = currentCabIndex; cabinetFileRow.Add(fileRow); continue; } // Update current cab size. currentPreCabSize += (ulong)fileRow.FileSize; if (currentPreCabSize > maxPreCabSizeInBytes) { // Overflow due to current file currentMediaRow = this.AddMediaRow(mediaTable, ++currentCabIndex, mediaTemplateRow.CompressionLevel); FileRowCollection cabinetFileRow = (FileRowCollection)this.cabinets[currentMediaRow]; fileRow.DiskId = currentCabIndex; cabinetFileRow.Add(fileRow); // Now files larger than MaxUncompressedMediaSize will be the only file in its cabinet so as to respect MaxUncompressedMediaSize currentPreCabSize = (ulong)fileRow.FileSize; } else { // File fits in the current cab. if (currentMediaRow == null) { // Create new cab and MediaRow currentMediaRow = this.AddMediaRow(mediaTable, ++currentCabIndex, mediaTemplateRow.CompressionLevel); } // Associate current file with current cab. FileRowCollection cabinetFileRow = (FileRowCollection)this.cabinets[currentMediaRow]; fileRow.DiskId = currentCabIndex; cabinetFileRow.Add(fileRow); } } // If there are uncompressed files and no MediaRow, create a default one. if (uncompressedFileRows.Count > 0 && mediaTable.Rows.Count == 0) { MediaRow defaultMediaRow = (MediaRow)mediaTable.CreateRow(null); defaultMediaRow.DiskId = 1; mediaRows.Add(defaultMediaRow); } }