/// <summary> /// Saves a library to a path on disk. /// </summary> /// <param name="path">Path to save library file to on disk.</param> /// <param name="binderFileManager">If provided, the binder file manager is used to bind files into the library.</param> /// <param name="wixVariableResolver">The Wix variable resolver.</param> public void Save(string path, BinderFileManager binderFileManager, WixVariableResolver wixVariableResolver) { FileMode fileMode = FileMode.Create; StringCollection fileIds = new StringCollection(); StringCollection files = new StringCollection(); int index = 0; // resolve paths to files and create the library cabinet file foreach (Section section in this.sections) { foreach (Table table in section.Tables) { foreach (Row row in table.Rows) { foreach (Field field in row.Fields) { ObjectField objectField = field as ObjectField; if (null != objectField) { if (null != binderFileManager && null != objectField.Data) { string cabinetFileId = (index++).ToString(CultureInfo.InvariantCulture); // resolve wix variables string resolvedValue = wixVariableResolver.ResolveVariables(row.SourceLineNumbers, (string)objectField.Data, false); files.Add(binderFileManager.ResolveFile(resolvedValue, table.Name, row.SourceLineNumbers, BindStage.Normal)); // File was successfully resolved so track this cabient file id. objectField.CabinetFileId = cabinetFileId; fileIds.Add(cabinetFileId); } else // clear out a previous cabinet file id value { objectField.CabinetFileId = null; } } } } } } // do not save the library if errors were found while resolving object paths if (wixVariableResolver.EncounteredError) { return; } // create the cabinet file if (0 < fileIds.Count) { using (WixCreateCab cab = new WixCreateCab(Path.GetFileName(path), Path.GetDirectoryName(path), fileIds.Count, 0, 0, CompressionLevel.Mszip)) { for (int i = 0; i < fileIds.Count; i++) { cab.AddFile(files[i], fileIds[i]); } cab.Complete(); } // append the library xml to the end of the newly created cabinet file fileMode = FileMode.Append; } // Assure the location to output the lib exists Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(path))); // save the xml using (FileStream fs = new FileStream(path, fileMode)) { XmlWriter writer = null; try { writer = new XmlTextWriter(fs, System.Text.Encoding.UTF8); writer.WriteStartDocument(); this.Persist(writer); writer.WriteEndDocument(); } finally { if (null != writer) { writer.Close(); } } } }
/// <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); } }
private void CreateContainer(ContainerInfo container, string manifestFile) { int payloadCount = container.Payloads.Count; // The number of embedded payloads if (!String.IsNullOrEmpty(manifestFile)) { ++payloadCount; } using (WixCreateCab cab = new WixCreateCab(Path.GetFileName(container.TempPath), Path.GetDirectoryName(container.TempPath), payloadCount, 0, 0, this.defaultCompressionLevel)) { // If a manifest was provided always add it as "payload 0" to the container. if (!String.IsNullOrEmpty(manifestFile)) { cab.AddFile(manifestFile, "0"); } foreach (PayloadInfoRow payload in container.Payloads) { Debug.Assert(PackagingType.Embedded == payload.Packaging); this.core.OnMessage(WixVerboses.LoadingPayload(payload.FullFileName)); cab.AddFile(payload.FullFileName, payload.EmbeddedId); } cab.Complete(); } }
/// <summary> /// Saves an outputs cab to a path on disk. /// </summary> /// <param name="path">Path to save outputs cab to on disk.</param> /// <param name="binderFileManager">If provided, the binder file manager is used to bind files into the outputs cab.</param> /// <param name="wixVariableResolver">The Wix variable resolver.</param> /// <param name="tempFilesLocation">Location for temporary files.</param> /// <returns>Returns true if a cabinet existed or was created, false otherwise.</returns> public bool SaveCab(string path, BinderFileManager binderFileManager, WixVariableResolver wixVariableResolver, string tempFilesLocation) { bool hasCab = false; // Check if there was a cab on the wixout when it was created if (null != this.cabPath) { // There was already a cab on the wixout when it was loaded. Reuse that one. File.Copy(this.cabPath, path, true); if (null != this.tempFileCollection) { this.tempFileCollection.Delete(); } hasCab = true; } else { int index = 0; Hashtable cabinets = new Hashtable(); StringCollection fileIds = new StringCollection(); StringCollection files = new StringCollection(); if (null != tempFilesLocation) { // resolve paths to files and create the output cabinet file if (0 == this.sections.Count) { Output.ResolveSectionFiles(this.tables, binderFileManager, wixVariableResolver, tempFilesLocation, cabinets, fileIds, files, ref index); } else { foreach (Section section in this.sections) { Output.ResolveSectionFiles(section.Tables, binderFileManager, wixVariableResolver, tempFilesLocation, cabinets, fileIds, files, ref index); } } } // extract files that come from cabinet files if (0 < cabinets.Count) { // ensure the temporary directory exists Directory.CreateDirectory(tempFilesLocation); foreach (DictionaryEntry cabinet in cabinets) { Uri baseUri = new Uri((string)cabinet.Key); string localPath; if ("embeddedresource" == baseUri.Scheme) { int bytesRead; byte[] buffer = new byte[512]; string originalLocalPath = Path.GetFullPath(baseUri.LocalPath.Substring(1)); string resourceName = baseUri.Fragment.Substring(1); Assembly assembly = Assembly.LoadFile(originalLocalPath); localPath = String.Concat(cabinet.Value, ".cab"); using (FileStream fs = File.OpenWrite(localPath)) { using (Stream resourceStream = assembly.GetManifestResourceStream(resourceName)) { while (0 < (bytesRead = resourceStream.Read(buffer, 0, buffer.Length))) { fs.Write(buffer, 0, bytesRead); } } } } else // normal file { localPath = baseUri.LocalPath; } // extract the cabinet's files into a temporary directory Directory.CreateDirectory((string)cabinet.Value); using (WixExtractCab extractCab = new WixExtractCab()) { extractCab.Extract(localPath, (string)cabinet.Value); } } } // create the cabinet file if (0 < fileIds.Count) { using (WixCreateCab cab = new WixCreateCab(Path.GetFileName(path), Path.GetDirectoryName(path), fileIds.Count, 0, 0, CompressionLevel.Mszip)) { for (int i = 0; i < fileIds.Count; i++) { cab.AddFile(files[i], fileIds[i]); } cab.Complete(); } // append the output xml to the end of the newly created cabinet file hasCab = true; } } return hasCab; }
/// <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(); } }