/// <summary> /// Creates a cabinet using the wixcab.dll interop layer. /// </summary> /// <param name="cabinetWorkItem">CabinetWorkItem containing information about the cabinet to create.</param> private void CreateCabinet(CabinetWorkItem cabinetWorkItem) { this.OnMessage(WixVerboses.CreateCabinet(cabinetWorkItem.CabinetFile)); int maxCabinetSize = 0; // The value of 0 corresponds to default of 2GB which means no cabinet splitting ulong maxPreCompressedSizeInBytes = 0; if (MaximumCabinetSizeForLargeFileSplitting != 0) { // User Specified Max Cab Size for File Splitting, So Check if this cabinet has a single file larger than MaximumUncompressedFileSize // If a file is larger than MaximumUncompressedFileSize, then the cabinet containing it will have only this file if (cabinetWorkItem.FileRows.Count == 1) { // Cabinet has Single File, Check if this is Large File than needs Splitting into Multiple cabs // Get the Value for Max Uncompressed Media Size maxPreCompressedSizeInBytes = (ulong)MaximumUncompressedMediaSize * 1024 * 1024; foreach (FileRow fileRow in cabinetWorkItem.FileRows) // No other easy way than looping to get the only row { if ((ulong)fileRow.FileSize >= maxPreCompressedSizeInBytes) { // If file is larger than MaximumUncompressedFileSize set Maximum Cabinet Size for Cabinet Splitting maxCabinetSize = MaximumCabinetSizeForLargeFileSplitting; } } } } // create the cabinet file string cabinetFileName = Path.GetFileName(cabinetWorkItem.CabinetFile); string cabinetDirectory = Path.GetDirectoryName(cabinetWorkItem.CabinetFile); using (WixCreateCab cab = new WixCreateCab(cabinetFileName, cabinetDirectory, cabinetWorkItem.FileRows.Count, maxCabinetSize, cabinetWorkItem.MaxThreshold, cabinetWorkItem.CompressionLevel)) { foreach (FileRow fileRow in cabinetWorkItem.FileRows) { bool retainRangeWarning; cabinetWorkItem.BinderFileManager.ResolvePatch(fileRow, out retainRangeWarning); if (retainRangeWarning) { // TODO: get patch family to add to warning message for PatchWiz parity. this.OnMessage(WixWarnings.RetainRangeMismatch(fileRow.SourceLineNumbers, fileRow.File)); } cab.AddFile(fileRow); } cab.Complete(newCabNamesCallBackAddress); } }
/// <summary> /// Creates a cabinet using the wixcab.dll interop layer. /// </summary> /// <param name="cabinetWorkItem">CabinetWorkItem containing information about the cabinet to create.</param> private void CreateCabinet(CabinetWorkItem cabinetWorkItem) { this.OnMessage(WixVerboses.CreateCabinet(cabinetWorkItem.CabinetFile)); // create the cabinet file string cabinetFileName = Path.GetFileName(cabinetWorkItem.CabinetFile); string cabinetDirectory = Path.GetDirectoryName(cabinetWorkItem.CabinetFile); try { using (WixCreateCab cab = new WixCreateCab(cabinetFileName, cabinetDirectory, 0, 0, cabinetWorkItem.CompressionLevel)) { foreach (FileRow fileRow in cabinetWorkItem.FileRows) { cab.AddFile(fileRow.Source, fileRow.File); } } } catch (FileNotFoundException e) { throw new WixException(WixErrors.FileNotFound(null, e.FileName)); } }
/// <summary> /// Creates a cabinet using the wixcab.dll interop layer. /// </summary> /// <param name="cabinetWorkItem">CabinetWorkItem containing information about the cabinet to create.</param> private void CreateCabinet(CabinetWorkItem cabinetWorkItem) { this.OnMessage(WixVerboses.CreateCabinet(cabinetWorkItem.CabinetFile)); // create the cabinet file string cabinetFileName = Path.GetFileName(cabinetWorkItem.CabinetFile); string cabinetDirectory = Path.GetDirectoryName(cabinetWorkItem.CabinetFile); using (WixCreateCab cab = new WixCreateCab(cabinetFileName, cabinetDirectory, cabinetWorkItem.FileRows.Count, 0, cabinetWorkItem.MaxThreshold, cabinetWorkItem.CompressionLevel)) { foreach (FileRow fileRow in cabinetWorkItem.FileRows) { bool retainRangeWarning; cabinetWorkItem.BinderFileManager.ResolvePatch(fileRow, out retainRangeWarning); if (retainRangeWarning) { // TODO: get patch family to add to warning message for PatchWiz parity. this.OnMessage(WixWarnings.RetainRangeMismatch(fileRow.SourceLineNumbers, fileRow.File)); } cab.AddFile(fileRow); } cab.Complete(); } }
/// <summary> /// Enqueues a CabinetWorkItem to the queue. /// </summary> /// <param name="cabinetWorkItem">cabinet work item</param> public void Enqueue(CabinetWorkItem cabinetWorkItem) { this.cabinetWorkItems.Enqueue(cabinetWorkItem); }
/// <summary> /// Creates a work item to create a cabinet. /// </summary> /// <param name="output">Output for the current database.</param> /// <param name="cabinetDir">Directory to create cabinet in.</param> /// <param name="mediaRow">MediaRow containing information about the cabinet.</param> /// <param name="fileRows">Collection of files in this cabinet.</param> /// <param name="fileTransfers">Array of files to be transfered.</param> /// <returns>created CabinetWorkItem object</returns> private CabinetWorkItem CreateCabinetWorkItem(Output output, string cabinetDir, MediaRow mediaRow, FileRowCollection fileRows, ArrayList fileTransfers) { CabinetWorkItem cabinetWorkItem = null; string tempCabinetFile = Path.Combine(this.TempFilesLocation, mediaRow.Cabinet); // check for an empty cabinet if (0 == fileRows.Count) { string cabinetName = mediaRow.Cabinet; // remove the leading '#' from the embedded cabinet name to make the warning easier to understand if (cabinetName.StartsWith("#", StringComparison.Ordinal)) { cabinetName = cabinetName.Substring(1); } // If building a patch, remind them to run -p for torch. if (OutputType.Patch == output.Type) { this.core.OnMessage(WixWarnings.EmptyCabinet(mediaRow.SourceLineNumbers, cabinetName, true)); } else { this.core.OnMessage(WixWarnings.EmptyCabinet(mediaRow.SourceLineNumbers, cabinetName)); } } CabinetBuildOption cabinetBuildOption = this.FileManager.ResolveCabinet(fileRows, ref tempCabinetFile); // create a cabinet work item if it's not being skipped if (CabinetBuildOption.BuildAndCopy == cabinetBuildOption || CabinetBuildOption.BuildAndMove == cabinetBuildOption) { int maxThreshold = 0; // default to the threshold for best smartcabbing (makes smallest cabinet). Cab.CompressionLevel compressionLevel = this.defaultCompressionLevel; if (mediaRow.HasExplicitCompressionLevel) { compressionLevel = mediaRow.CompressionLevel; } cabinetWorkItem = new CabinetWorkItem(fileRows, tempCabinetFile, maxThreshold, compressionLevel, this.FileManager); } else // reuse the cabinet from the cabinet cache. { this.core.OnMessage(WixVerboses.ReusingCabCache(mediaRow.SourceLineNumbers, mediaRow.Cabinet, tempCabinetFile)); try { // Ensure the cached cabinet timestamp is current to prevent perpetual incremental builds. The // problematic scenario goes like this. Imagine two cabinets in the cache. Update a file that // goes into one of the cabinets. One cabinet will get rebuilt, the other will be copied from // the cache. Now the file (an input) has a newer timestamp than the reused cabient (an output) // causing the project to look like it perpetually needs a rebuild until all of the reused // cabinets get newer timestamps. File.SetLastWriteTime(tempCabinetFile, DateTime.Now); } catch (Exception e) { this.core.OnMessage(WixWarnings.CannotUpdateCabCache(mediaRow.SourceLineNumbers, tempCabinetFile, e.Message)); } } if (mediaRow.Cabinet.StartsWith("#", StringComparison.Ordinal)) { Table streamsTable = output.EnsureTable(this.core.TableDefinitions["_Streams"]); Row streamRow = streamsTable.CreateRow(null); streamRow[0] = mediaRow.Cabinet.Substring(1); streamRow[1] = tempCabinetFile; } else { string destinationPath = Path.Combine(cabinetDir, mediaRow.Cabinet); FileTransfer transfer; if (FileTransfer.TryCreate(tempCabinetFile, destinationPath, CabinetBuildOption.BuildAndMove == cabinetBuildOption, "Cabinet", mediaRow.SourceLineNumbers, out transfer)) { transfer.Built = true; fileTransfers.Add(transfer); } } return cabinetWorkItem; }