diff --git a/README.md b/README.md index 4a6ac0f..43649af 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,25 @@ -# TemplatePackageFix -Fix SharePoint site template template saved in WSP package + +TemplatePackageFix by [Plumsail team](http://plumsail.com) +========= + +## Synopsis + +This project present a small utility which can move all your workflows inside the package to another feature. + +It can be useful if you create a site template from the SharePoint site where was deployed [Workflow Actions Pack](http://plumsail.com/workflow-actions-pack/). + +## How to use + +[Download](https://github.com/RFlipper/TemplatePackageFix/releases) the utility and extract it to any directory. + +Start TemplatePackageFix.exe from command line with specifying the path to your WSP package. +Example: ```TemplatePackageFix.exe C:\temp\HelpDeskTemplate.wsp``` + + +## Contributors + +Currently only I'm, but you're welcome. + +## Post Scriptum + +To know more please check out the article [Deploy SharePoint 2013 Workflow via Site Template](http://plumsail.com/blog/2015/01/deploy-sharepoint-2013-workflow-via-site-template/) diff --git a/TemplatePackageFix/Fixer.cs b/TemplatePackageFix/Fixer.cs new file mode 100644 index 0000000..fac22a2 --- /dev/null +++ b/TemplatePackageFix/Fixer.cs @@ -0,0 +1,222 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using System.Xml.Linq; +using Plumsail.TemplatePackageFix.Helpers; + +namespace Plumsail.TemplatePackageFix +{ + public sealed class Fixer + { + #region Declarations + readonly XNamespace ns = "http://schemas.microsoft.com/sharepoint/"; + readonly string WFPackSolutionID = "64283c6e-6aea-4a86-a881-042359b3521a"; + readonly string WFFeaturePath = "SP2013Workflows"; + readonly string BasePath; + + private XDocument wfFeature; + private XDocument wfElements; + private string wfFeatureDir; + #endregion + + #region Constructor + public Fixer(string path) + { + BasePath = path; + CreateWorkflowFeature(); + ProcessManifest(); + } + #endregion + + #region Control methods + internal void ProcessManifest() + { + var manifestFilePath = Path.Combine(BasePath, "manifest.xml"); + + //Load features + var manifest = XDocument.Load(manifestFilePath); + var features = manifest.Descendants(ns + "FeatureManifest"); + + //Process features list defined in manifest.xml + foreach (var featureDef in features) + { + var featureFile = Path.Combine(BasePath, featureDef.Attribute("Location").Value); + ProcessFeature(featureFile); + } + + //Add additional workflow nodes to manifest.xml + manifest.Descendants(ns + "FeatureManifests").Single().Add( + new XElement(ns + "FeatureManifest", + new XAttribute("Location", Path.Combine(WFFeaturePath, "Feature.xml")))); + + wfElements.SaveToFile(Path.Combine(BasePath, WFFeaturePath, "Elements.xml")); + wfFeature.SaveToFile(Path.Combine(BasePath, WFFeaturePath, "Feature.xml")); + + RemovePackageDependency(manifest); + + manifest.SaveToFile(manifestFilePath); + } + + internal void ProcessFeature(string featureFile) + { + var featureDir = Path.GetDirectoryName(featureFile); + var elementsFile = Path.Combine(featureDir, "Elements.xml"); + + var feature = XDocument.Load(featureFile); + var elements = XDocument.Load(elementsFile); + + RemoveCustomActions(feature, elements, featureDir); + RemoveModules(feature, elements, featureDir); + RemoveDependentFeatures(feature, elements, featureDir); + MoveWorkflowModules(feature, elements, featureDir); + + //Save files + elements.SaveToFile(elementsFile); + feature.SaveToFile(featureFile); + } + #endregion + + #region Service methods + + internal void CreateWorkflowFeature() + { + wfFeatureDir = Path.Combine(BasePath, WFFeaturePath); + System.IO.Directory.CreateDirectory(wfFeatureDir); + wfFeature = new XDocument( + new XElement(ns + "Feature", + new XAttribute("Id", Guid.NewGuid().ToString()), + new XAttribute("Title", "Template workflows"), + new XAttribute("Description", "Template workflows"), + new XAttribute("Scope", "Web"), + new XAttribute("Version", "1.0.0.0"), + new XElement(ns + "ElementManifests", + new XElement(ns + "ElementManifest", new XAttribute("Location", "Elements.xml"))) + )); + + wfElements = new XDocument(new XElement(ns + "Elements")); + } + + private void MoveWorkflowModules(XDocument feature, XDocument elements, string featureDir) + { + Expression> ex = el => el.Attribute("Location").Value.Contains("\\wfsvc\\"); + var apNodes = + feature.Descendants(ns + "ElementFile") + .Where(el => el.Attribute("Location").Value.Contains("\\wfsvc\\") + && !el.Attribute("Location").Value.Contains("Schema.xml")); + + if (apNodes.Count() < 1) + return; + + var paths = new HashSet(); + foreach (var elementFile in apNodes) + { + var fileRelativePath = elementFile.Attribute("Location").Value; + var fileName = Path.GetFileName(fileRelativePath); + var filePath = Path.GetDirectoryName(fileRelativePath); + paths.Add(filePath); + + Directory.CreateDirectory(Path.Combine(wfFeatureDir, filePath)); + File.Move(Path.Combine(featureDir, fileRelativePath), Path.Combine(wfFeatureDir, fileRelativePath)); + } + + wfFeature.Descendants(ns + "ElementManifests").Single().Add(apNodes); + apNodes.Remove(); + + var elNodes = elements.Descendants(ns + "Module").Where(el => paths.Contains(el.Attribute("Path").Value)); + wfElements.Root.Add(elNodes); + elNodes.Remove(); + } + + private void RemoveDependentFeatures(XDocument feature, XDocument elements, string featureDir) + { + var onet = feature.Descendants(ns + "ElementFile").SingleOrDefault(el => el.Attribute("Location").Value.Contains("\\ONet.xml")); + if (onet == null) + return; + + var onetFilePath = Path.Combine(featureDir, onet.Attribute("Location").Value); + var onetDocument = XDocument.Load(onetFilePath); + var features = onetDocument.Descendants(ns + "Feature") + .Where(el => el.Attribute("ID").Value == "{9a5d1295-65c0-4c8e-a926-968da90d2ef9}" + || el.Attribute("ID").Value == "{d7891031-e7f5-4734-8077-9189dd35551c}"); + + if (features.Count() < 1) + return; + + features.Remove(); + onetDocument.SaveToFile(onetFilePath); + } + + private void RemoveCustomActions(XDocument feature, XDocument elements, string featureDir) + { + var nodes = elements.Descendants(ns + "CustomAction") + .Where(el => el.Attribute("Id").Value.Contains("WFPackAdminPage") + || (el.Attribute("ScriptSrc") != null && el.Attribute("ScriptSrc").Value.Contains("Plumsail"))); + + if (nodes.Count() < 1) + return; + + nodes.Remove(); + } + + private void RemoveModules(XDocument feature, XDocument elements, string featureDir) + { + var workflowFiles = + feature.Descendants(ns + "ElementFile") + .Where(el => el.Attribute("Location").Value.Contains("\\Workflows\\")); + + if (workflowFiles.Count() < 1) + return; + + //Get list of nodes to remove from Elements.xml + var filesToRemove = new List(); + foreach (var elementFile in workflowFiles) + { + var fileRelativePath = elementFile.Attribute("Location").Value; + var fileName = Path.GetFileName(fileRelativePath); + var filePath = Path.GetDirectoryName(fileRelativePath); + + var fileNode = elements.Descendants(ns + "File").FirstOrDefault( + el => el.Parent.Attribute("Path").Value == filePath + && el.Attribute("Path").Value == fileName); + + if (fileNode != null) + filesToRemove.Add(fileNode); + + //Delete physical file + File.Delete(Path.Combine(featureDir, fileRelativePath)); + } + + //Remove nodes from Elements.xml + filesToRemove.ForEach(el => el.Remove()); + //Remove empty module elements + elements.Descendants(ns + "Module").Where(el => !el.HasElements).Remove(); + + //Remove nodes from Feature.xml + workflowFiles.Remove(); + } + + private void RemovePackageDependency(XDocument manifest) + { + var dependencyNode = manifest.Descendants(ns + "ActivationDependency") + .SingleOrDefault(el => el.Attribute("SolutionId").Value == WFPackSolutionID); + + if (dependencyNode == null) + return; + + var parent = dependencyNode.Parent; + + dependencyNode.Remove(); + + //remove empty ActivationDependencies node + if (!parent.HasElements) + parent.Remove(); + } + #endregion + + } +} diff --git a/TemplatePackageFix/Helpers/Extensions.cs b/TemplatePackageFix/Helpers/Extensions.cs new file mode 100644 index 0000000..8a29d8a --- /dev/null +++ b/TemplatePackageFix/Helpers/Extensions.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using System.Xml.Linq; + +namespace Plumsail.TemplatePackageFix.Helpers +{ + public static class Extensions + { + public static void SaveToFile(this XDocument doc, string path) + { + var settings = new XmlWriterSettings() + { + OmitXmlDeclaration = true + , Indent = true + , IndentChars = "\t" + , NewLineChars = Environment.NewLine + , NewLineHandling = NewLineHandling.Replace + }; + using (var stream = System.IO.File.Create(path)) + { + using (var writer = XmlWriter.Create(stream, settings)) + { + doc.Save(writer); + } + } + } + + } +} diff --git a/TemplatePackageFix/Models/Solution.cs b/TemplatePackageFix/Models/Solution.cs new file mode 100644 index 0000000..d407155 --- /dev/null +++ b/TemplatePackageFix/Models/Solution.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Plumsail.TemplatePackageFix.Models +{ + public class Solution + { + public class FeatureManifest + { + public string Location { get; set; } + } + + public class ActivationDependency + { + public Guid SolutionId { get; set; } + public string SolutionName { get; set; } + } + + public Guid SolutionId { get; set; } + public string SharePointProductVersion { get; set; } + + public List FeatureManifests { get; set; } + public List ActivationDependencies { get; set; } + } +} diff --git a/TemplatePackageFix/Packer.cs b/TemplatePackageFix/Packer.cs new file mode 100644 index 0000000..3a2ce5b --- /dev/null +++ b/TemplatePackageFix/Packer.cs @@ -0,0 +1,39 @@ +using Microsoft.Deployment.Compression; +using Microsoft.Deployment.Compression.Cab; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Plumsail.TemplatePackageFix +{ + /// + /// Wrap pack/unpack functionality + /// + public class Packer : IDisposable + { + public readonly string OriginalPath; + public readonly string TempFolder = Path.GetTempPath() + Guid.NewGuid(); + + public Packer(string path) + { + OriginalPath = path; + + Directory.CreateDirectory(TempFolder); + if (File.Exists(OriginalPath)) + { + var cab = new CabInfo(OriginalPath); + cab.Unpack(TempFolder); + } + } + public void Dispose() + { + var cab = new CabInfo(OriginalPath); + cab.Pack(TempFolder, true, CompressionLevel.Normal, (sender, args) => { }); + + Directory.Delete(TempFolder, true); + } + } +} diff --git a/TemplatePackageFix/Program.cs b/TemplatePackageFix/Program.cs new file mode 100644 index 0000000..63f16fa --- /dev/null +++ b/TemplatePackageFix/Program.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Plumsail.TemplatePackageFix +{ + class Program + { + static void Main(string[] args) + { + if (args.Length < 1) + { + var message = @"Example: TemplatePackageFix.exe C:\temp\HelpDeskTemplate.wsp" + + "\nThe program will remove any Plumsail Dependencies from the web template package."; + + Console.WriteLine(message); + return; + } + + var path = args[0]; + Console.Write("Processing file {0} ", path); + using (var packer = new Packer(path)) + { + var baseTempFolder = packer.TempFolder; + new Fixer(baseTempFolder); + } + + Console.WriteLine(" - fixed"); + } + } +} diff --git a/TemplatePackageFix/Properties/AssemblyInfo.cs b/TemplatePackageFix/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d5dced0 --- /dev/null +++ b/TemplatePackageFix/Properties/AssemblyInfo.cs @@ -0,0 +1,38 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("TemplatePackageFix")] +[assembly: AssemblyDescription("The utility moves workflows from WSP package to separate feature")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Plumsail.com")] +[assembly: AssemblyProduct("TemplatePackageFix")] +[assembly: AssemblyCopyright("Copyright Plumsail © 2015")] +[assembly: AssemblyTrademark("Plumsail.com")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("7436d9f8-545b-4b9e-8dd8-af48673676b0")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] + +[assembly: InternalsVisibleTo("TemplatePackageFix.Tests")] \ No newline at end of file diff --git a/TemplatePackageFix/Reference/Microsoft.Deployment.Compression.Cab.dll b/TemplatePackageFix/Reference/Microsoft.Deployment.Compression.Cab.dll new file mode 100644 index 0000000..8f94432 Binary files /dev/null and b/TemplatePackageFix/Reference/Microsoft.Deployment.Compression.Cab.dll differ diff --git a/TemplatePackageFix/Reference/Microsoft.Deployment.Compression.Cab.xml b/TemplatePackageFix/Reference/Microsoft.Deployment.Compression.Cab.xml new file mode 100644 index 0000000..8fded2a --- /dev/null +++ b/TemplatePackageFix/Reference/Microsoft.Deployment.Compression.Cab.xml @@ -0,0 +1,490 @@ + + + + Microsoft.Deployment.Compression.Cab + + + + + Disposes of resources allocated by the cabinet engine. + + If true, the method has been called directly or indirectly by a user's code, + so managed and unmanaged resources will be disposed. If false, the method has been called by the + runtime from inside the finalizer, and only unmanaged resources will be disposed. + + + + Disposes of resources allocated by the cabinet engine. + + If true, the method has been called directly or indirectly by a user's code, + so managed and unmanaged resources will be disposed. If false, the method has been called by the + runtime from inside the finalizer, and only unmanaged resources will be disposed. + + + + Engine capable of packing and unpacking archives in the cabinet format. + + + + + Creates a new instance of the cabinet engine. + + + + + Disposes of resources allocated by the cabinet engine. + + If true, the method has been called directly + or indirectly by a user's code, so managed and unmanaged resources + will be disposed. If false, the method has been called by the runtime + from inside the finalizer, and only unmanaged resources will be + disposed. + + + + Creates a cabinet or chain of cabinets. + + A context interface to handle opening + and closing of cabinet and file streams. + The paths of the files in the archive (not + external file paths). + The maximum number of bytes for one + cabinet before the contents are chained to the next cabinet, or zero + for unlimited cabinet size. + The cabinet could not be + created. + + The stream context implementation may provide a mapping from the + file paths within the cabinet to the external file paths. + Smaller folder sizes can make it more efficient to extract + individual files out of large cabinet packages. + + + + + Checks whether a Stream begins with a header that indicates + it is a valid cabinet file. + + Stream for reading the cabinet file. + True if the stream is a valid cabinet file + (with no offset); false otherwise. + + + + Gets information about files in a cabinet or cabinet chain. + + A context interface to handle opening + and closing of cabinet and file streams. + A predicate that can determine + which files to process, optional. + Information about files in the cabinet stream. + The cabinet provided + by the stream context is not valid. + + The predicate takes an internal file + path and returns true to include the file or false to exclude it. + + + + + Extracts files from a cabinet or cabinet chain. + + A context interface to handle opening + and closing of cabinet and file streams. + An optional predicate that can determine + which files to process. + The cabinet provided + by the stream context is not valid. + + The predicate takes an internal file + path and returns true to include the file or false to exclude it. + + + + + Exception class for cabinet operations. + + + + + Creates a new CabException with a specified error message and a reference to the + inner exception that is the cause of this exception. + + The message that describes the error. + The exception that is the cause of the current exception. If the + innerException parameter is not a null reference (Nothing in Visual Basic), the current exception + is raised in a catch block that handles the inner exception. + + + + Creates a new CabException with a specified error message. + + The message that describes the error. + + + + Creates a new CabException. + + + + + Initializes a new instance of the CabException class with serialized data. + + The SerializationInfo that holds the serialized object data about the exception being thrown. + The StreamingContext that contains contextual information about the source or destination. + + + + Sets the SerializationInfo with information about the exception. + + The SerializationInfo that holds the serialized object data about the exception being thrown. + The StreamingContext that contains contextual information about the source or destination. + + + + Gets the FCI or FDI cabinet engine error number. + + A cabinet engine error number, or 0 if the exception was + not related to a cabinet engine error number. + + + + Gets the Win32 error code. + + A Win32 error code, or 0 if the exception was + not related to a Win32 error. + + + + Disposes of resources allocated by the cabinet engine. + + If true, the method has been called directly or indirectly by a user's code, + so managed and unmanaged resources will be disposed. If false, the method has been called by the + runtime from inside the finalizer, and only unmanaged resources will be disposed. + + + + Object representing a compressed file within a cabinet package; provides operations for getting + the file properties and extracting the file. + + + + + Creates a new CabinetFileInfo object representing a file within a cabinet in a specified path. + + An object representing the cabinet containing the file. + The path to the file within the cabinet. Usually, this is a simple file + name, but if the cabinet contains a directory structure this may include the directory. + + + + Creates a new CabinetFileInfo object with all parameters specified, + used internally when reading the metadata out of a cab. + + The internal path and name of the file in the cab. + The folder number containing the file. + The cabinet number where the file starts. + The stored attributes of the file. + The stored last write time of the file. + The uncompressed size of the file. + + + + Initializes a new instance of the CabinetFileInfo class with serialized data. + + The SerializationInfo that holds the serialized object data about the exception being thrown. + The StreamingContext that contains contextual information about the source or destination. + + + + Sets the SerializationInfo with information about the archive. + + The SerializationInfo that holds the serialized object data. + The StreamingContext that contains contextual information + about the source or destination. + + + + Refreshes the information in this object with new data retrieved + from an archive. + + Fresh instance for the same file just + read from the archive. + + This implementation refreshes the . + + + + + Gets or sets the cabinet that contains this file. + + + The CabinetInfo instance that retrieved this file information -- this + may be null if the CabinetFileInfo object was returned directly from a + stream. + + + + + Gets the full path of the cabinet that contains this file. + + The full path of the cabinet that contains this file. + + + + Gets the number of the folder containing this file. + + The number of the cabinet folder containing this file. + A single folder or the first folder of a cabinet + (or chain of cabinets) is numbered 0. + + + + Object representing a cabinet file on disk; provides access to + file-based operations on the cabinet file. + + + Generally, the methods on this class are much easier to use than the + stream-based interfaces provided by the class. + + + + + Creates a new CabinetInfo object representing a cabinet file in a specified path. + + The path to the cabinet file. When creating a cabinet file, this file does not + necessarily exist yet. + + + + Initializes a new instance of the CabinetInfo class with serialized data. + + The SerializationInfo that holds the serialized object data about the exception being thrown. + The StreamingContext that contains contextual information about the source or destination. + + + + Creates a compression engine that does the low-level work for + this object. + + A new instance. + + Each instance will be d + immediately after use. + + + + + Gets information about the files contained in the archive. + + A list of objects, each + containing information about a file in the archive. + + + + Gets information about the certain files contained in the archive file. + + The search string, such as + "*.txt". + A list of objects, each containing + information about a file in the archive. + + + + Generic class for managing allocations of integer handles + for objects of a certain type. + + The type of objects the handles refer to. + + + + Auto-resizing list of objects for which handles have been allocated. + Each handle is just an index into this list. When a handle is freed, + the list item at that index is set to null. + + + + + Creates a new HandleManager instance. + + + + + Allocates a new handle for an object. + + Object that the handle will refer to. + New handle that can be later used to retrieve the object. + + + + Frees a handle that was previously allocated. Afterward the handle + will be invalid and the object it referred to can no longer retrieved. + + Handle to be freed. + + + + Gets the object of a handle, or null if the handle is invalid. + + The integer handle previously allocated + for the desired object. + The object for which the handle was allocated. + + + + Native DllImport methods and related structures and constants used for + cabinet creation and extraction via cabinet.dll. + + + + + A direct import of constants, enums, structures, delegates, and functions from fci.h. + Refer to comments in fci.h for documentation. + + + + + Error codes that can be returned by FCI. + + + + + FCI compression algorithm types and parameters. + + + + + Reason for FCI status callback. + + + + + Cabinet information structure used for FCI initialization and GetNextCabinet callback. + + + + + Ensures that the FCI handle is safely released. + + + + + Creates a new unintialized handle. The handle will be initialized + when it is marshalled back from native code. + + + + + Releases the handle by calling FDIDestroy(). + + True if the release succeeded. + + + + Checks if the handle is invalid. An FCI handle is invalid when it is zero. + + + + + A direct import of constants, enums, structures, delegates, and functions from fdi.h. + Refer to comments in fdi.h for documentation. + + + + + Error codes that can be returned by FDI. + + + + + Type of notification message for the FDI Notify callback. + + + + + Cabinet information structure filled in by FDI IsCabinet. + + + + + Cabinet notification details passed to the FDI Notify callback. + + + + + Ensures that the FDI handle is safely released. + + + + + Creates a new unintialized handle. The handle will be initialized + when it is marshalled back from native code. + + + + + Releases the handle by calling FDIDestroy(). + + True if the release succeeded. + + + + Checks if the handle is invalid. An FDI handle is invalid when it is zero. + + + + + Error info structure for FCI and FDI. + + Before being passed to FCI or FDI, this structure is + pinned in memory via a GCHandle. The pinning is necessary + to be able to read the results, since the ERF structure doesn't + get marshalled back out after an error. + + + + Clears the error information. + + + + + Gets or sets the cabinet error code. + + + + + Gets or sets the Win32 error code. + + + + + GCHandle doesn't like the bool type, so use an int underneath. + + + + + Distribution specific strings. + + + + + News URL for the distribution. + + + + + Short product name for the distribution. + + + + + Support URL for the distribution. + + + + + Telemetry URL format for the distribution. + + + + diff --git a/TemplatePackageFix/Reference/Microsoft.Deployment.Compression.dll b/TemplatePackageFix/Reference/Microsoft.Deployment.Compression.dll new file mode 100644 index 0000000..81da5f5 Binary files /dev/null and b/TemplatePackageFix/Reference/Microsoft.Deployment.Compression.dll differ diff --git a/TemplatePackageFix/Reference/Microsoft.Deployment.Compression.xml b/TemplatePackageFix/Reference/Microsoft.Deployment.Compression.xml new file mode 100644 index 0000000..e27bb82 --- /dev/null +++ b/TemplatePackageFix/Reference/Microsoft.Deployment.Compression.xml @@ -0,0 +1,1960 @@ + + + + Microsoft.Deployment.Compression + + + + + Base exception class for compression operations. Compression libraries should + derive subclass exceptions with more specific error information relevent to the + file format. + + + + + Creates a new ArchiveException with a specified error message and a reference to the + inner exception that is the cause of this exception. + + The message that describes the error. + The exception that is the cause of the current exception. If the + innerException parameter is not a null reference (Nothing in Visual Basic), the current exception + is raised in a catch block that handles the inner exception. + + + + Creates a new ArchiveException with a specified error message. + + The message that describes the error. + + + + Creates a new ArchiveException. + + + + + Initializes a new instance of the ArchiveException class with serialized data. + + The SerializationInfo that holds the serialized object data about the exception being thrown. + The StreamingContext that contains contextual information about the source or destination. + + + + Abstract object representing a compressed file within an archive; + provides operations for getting the file properties and unpacking + the file. + + + + + Creates a new ArchiveFileInfo object representing a file within + an archive in a specified path. + + An object representing the archive + containing the file. + The path to the file within the archive. + Usually, this is a simple file name, but if the archive contains + a directory structure this may include the directory. + + + + Creates a new ArchiveFileInfo object with all parameters specified; + used by subclasses when reading the metadata out of an archive. + + The internal path and name of the file in + the archive. + The archive number where the file + starts. + The stored attributes of the file. + The stored last write time of the + file. + The uncompressed size of the file. + + + + Initializes a new instance of the ArchiveFileInfo class with + serialized data. + + The SerializationInfo that holds the serialized + object data about the exception being thrown. + The StreamingContext that contains contextual + information about the source or destination. + + + + Sets the SerializationInfo with information about the archive. + + The SerializationInfo that holds the serialized + object data. + The StreamingContext that contains contextual + information about the source or destination. + + + + Gets the full path to the file. + + The same as + + + + Deletes the file. NOT SUPPORTED. + + Files cannot be deleted + from an existing archive. + + + + Refreshes the attributes and other cached information about the file, + by re-reading the information from the archive. + + + + + Extracts the file. + + The destination path where the file + will be extracted. + + + + Extracts the file, optionally overwriting any existing file. + + The destination path where the file + will be extracted. + If true, + will be overwritten if it exists. + is false + and exists. + + + + Opens the archive file for reading without actually extracting the + file to disk. + + + A stream for reading directly from the packed file. Like any stream + this should be closed/disposed as soon as it is no longer needed. + + + + + Opens the archive file reading text with UTF-8 encoding without + actually extracting the file to disk. + + + A reader for reading text directly from the packed file. Like any reader + this should be closed/disposed as soon as it is no longer needed. + + + To open an archived text file with different encoding, use the + method and pass the returned stream to one of + the constructor overloads. + + + + + Refreshes the information in this object with new data retrieved + from an archive. + + Fresh instance for the same file just + read from the archive. + + Subclasses may override this method to refresh sublcass fields. + However they should always call the base implementation first. + + + + + Gets the name of the file. + + The name of the file, not including any path. + + + + Gets the internal path of the file in the archive. + + The internal path of the file in the archive, not including + the file name. + + + + Gets the full path to the file. + + The full path to the file, including the full path to the + archive, the internal path in the archive, and the file name. + + For example, the path "C:\archive.cab\file.txt" refers to + a file "file.txt" inside the archive "archive.cab". + + + + + Gets or sets the archive that contains this file. + + + The ArchiveInfo instance that retrieved this file information -- this + may be null if the ArchiveFileInfo object was returned directly from + a stream. + + + + + Gets the full path of the archive that contains this file. + + The full path of the archive that contains this file. + + + + Gets the number of the archive where this file starts. + + The number of the archive where this file starts. + A single archive or the first archive in a chain is + numbered 0. + + + + Checks if the file exists within the archive. + + True if the file exists, false otherwise. + + + + Gets the uncompressed size of the file. + + The uncompressed size of the file in bytes. + + + + Gets the attributes of the file. + + The attributes of the file as stored in the archive. + + + + Gets the last modification time of the file. + + The last modification time of the file as stored in the + archive. + + + + Abstract object representing a compressed archive on disk; + provides access to file-based operations on the archive. + + + + + Creates a new ArchiveInfo object representing an archive in a + specified path. + + The path to the archive. When creating an archive, + this file does not necessarily exist yet. + + + + Initializes a new instance of the ArchiveInfo class with serialized data. + + The SerializationInfo that holds the serialized object + data about the exception being thrown. + The StreamingContext that contains contextual + information about the source or destination. + + + + Gets the full path of the archive. + + The full path of the archive. + + + + Deletes the archive. + + + + + Copies an existing archive to another location. + + The destination file path. + + + + Copies an existing archive to another location, optionally + overwriting the destination file. + + The destination file path. + If true, the destination file will be + overwritten if it exists. + + + + Moves an existing archive to another location. + + The destination file path. + + + + Checks if the archive contains a valid archive header. + + True if the file is a valid archive; false otherwise. + + + + Gets information about the files contained in the archive. + + A list of objects, each + containing information about a file in the archive. + + + + Gets information about the certain files contained in the archive file. + + The search string, such as + "*.txt". + A list of objects, each containing + information about a file in the archive. + + + + Extracts all files from an archive to a destination directory. + + Directory where the files are to be + extracted. + + + + Extracts all files from an archive to a destination directory, + optionally extracting only newer files. + + Directory where the files are to be + extracted. + Handler for receiving progress + information; this may be null if progress is not desired. + + + + Extracts a single file from the archive. + + The name of the file in the archive. Also + includes the internal path of the file, if any. File name matching + is case-insensitive. + The path where the file is to be + extracted on disk. + If already exists, + it will be overwritten. + + + + Extracts multiple files from the archive. + + The names of the files in the archive. + Each name includes the internal path of the file, if any. File name + matching is case-insensitive. + This parameter may be null, but if + specified it is the root directory for any relative paths in + . + The paths where the files are to be + extracted on disk. If this parameter is null, the files will be + extracted with the names from the archive. + + If any extracted files already exist on disk, they will be overwritten. +

The and + parameters cannot both be null.

+
+
+ + + Extracts multiple files from the archive, optionally extracting + only newer files. + + The names of the files in the archive. + Each name includes the internal path of the file, if any. File name + matching is case-insensitive. + This parameter may be null, but if + specified it is the root directory for any relative paths in + . + The paths where the files are to be + extracted on disk. If this parameter is null, the files will be + extracted with the names from the archive. + Handler for receiving progress information; + this may be null if progress is not desired. + + If any extracted files already exist on disk, they will be overwritten. +

The and + parameters cannot both be null.

+
+
+ + + Extracts multiple files from the archive. + + A mapping from internal file paths to + external file paths. Case-senstivity when matching internal paths + depends on the IDictionary implementation. + This parameter may be null, but if + specified it is the root directory for any relative external paths + in . + + If any extracted files already exist on disk, they will be overwritten. + + + + + Extracts multiple files from the archive. + + A mapping from internal file paths to + external file paths. Case-senstivity when matching internal + paths depends on the IDictionary implementation. + This parameter may be null, but if + specified it is the root directory for any relative external + paths in . + Handler for receiving progress + information; this may be null if progress is not desired. + + If any extracted files already exist on disk, they will be overwritten. + + + + + Opens a file inside the archive for reading without actually + extracting the file to disk. + + The name of the file in the archive. Also + includes the internal path of the file, if any. File name matching + is case-insensitive. + + A stream for reading directly from the packed file. Like any stream + this should be closed/disposed as soon as it is no longer needed. + + + + + Opens a file inside the archive for reading text with UTF-8 encoding + without actually extracting the file to disk. + + The name of the file in the archive. Also + includes the internal path of the file, if any. File name matching + is case-insensitive. + + A reader for reading text directly from the packed file. Like any reader + this should be closed/disposed as soon as it is no longer needed. + + + To open an archived text file with different encoding, use the + method and pass the returned stream to one of + the constructor overloads. + + + + + Compresses all files in a directory into the archive. + Does not include subdirectories. + + The directory containing the + files to be included. + + Uses maximum compression level. + + + + + Compresses all files in a directory into the archive, optionally + including subdirectories. + + This is the root directory + for to pack all files. + If true, recursively include + files in subdirectories. + The compression level used when creating + the archive. + Handler for receiving progress information; + this may be null if progress is not desired. + + The files are stored in the archive using their relative file paths in + the directory tree, if supported by the archive file format. + + + + + Compresses files into the archive, specifying the names used to + store the files in the archive. + + This parameter may be null, but + if specified it is the root directory + for any relative paths in . + The list of files to be included in + the archive. + The names of the files as they are stored + in the archive. Each name + includes the internal path of the file, if any. This parameter may + be null, in which case the files are stored in the archive with their + source file names and no path information. + + Uses maximum compression level. +

Duplicate items in the array will cause + an .

+
+
+ + + Compresses files into the archive, specifying the names used to + store the files in the archive. + + This parameter may be null, but if + specified it is the root directory + for any relative paths in . + The list of files to be included in + the archive. + The names of the files as they are stored in + the archive. Each name includes the internal path of the file, if any. + This parameter may be null, in which case the files are stored in the + archive with their source file names and no path information. + The compression level used when creating the + archive. + Handler for receiving progress information; + this may be null if progress is not desired. + + Duplicate items in the array will cause + an . + + + + + Compresses files into the archive, specifying the names used + to store the files in the archive. + + This parameter may be null, but if + specified it is the root directory + for any relative paths in . + A mapping from internal file paths to + external file paths. + + Uses maximum compression level. + + + + + Compresses files into the archive, specifying the names used to + store the files in the archive. + + This parameter may be null, but if + specified it is the root directory + for any relative paths in . + A mapping from internal file paths to + external file paths. + The compression level used when creating + the archive. + Handler for receiving progress information; + this may be null if progress is not desired. + + + + Given a directory, gets the relative paths of all files in the + directory, optionally including all subdirectories. + + The directory to search. + True to include subdirectories + in the search. + A list of file paths relative to the directory. + + + + Retrieves information about one file from this archive. + + Path of the file in the archive. + File information, or null if the file was not found + in the archive. + + + + Creates a compression engine that does the low-level work for + this object. + + A new compression engine instance that matches the specific + subclass of archive. + + Each instance will be d + immediately after use. + + + + + Creates a case-insensitive dictionary mapping from one list of + strings to the other. + + List of keys. + List of values that are mapped 1-to-1 to + the keys. + A filled dictionary of the strings. + + + + Recursive-descent helper function for + GetRelativeFilePathsInDirectoryTree. + + The root directory of the search. + The relative directory to be + processed now. + True to descend into + subdirectories. + List of files found so far. + + + + Uses a CompressionEngine to get ArchiveFileInfo objects from this + archive, and then associates them with this ArchiveInfo instance. + + Optional predicate that can determine + which files to process. + A list of objects, each + containing information about a file in the archive. + + + + Gets the directory that contains the archive. + + A DirectoryInfo object representing the parent directory of the + archive. + + + + Gets the full path of the directory that contains the archive. + + The full path of the directory that contains the archive. + + + + Gets the size of the archive. + + The size of the archive in bytes. + + + + Gets the file name of the archive. + + The file name of the archive, not including any path. + + + + Checks if the archive exists. + + True if the archive exists; else false. + + + + Contains the data reported in an archive progress event. + + + + + Creates a new ArchiveProgressEventArgs object from specified event parameters. + + type of status message + name of the file being processed + number of the current file being processed + total number of files to be processed + number of bytes processed so far when compressing or extracting a file + total number of bytes in the current file + name of the current Archive + current Archive number, when processing a chained set of Archives + total number of Archives in a chained set + number of compressed bytes processed so far during an extraction + total number of compressed bytes to be processed during an extraction + number of uncompressed file bytes processed so far + total number of uncompressed file bytes to be processed + + + + Gets the type of status message. + + A value indicating what type of progress event occurred. + + The handler may choose to ignore some types of progress events. + For example, if the handler will only list each file as it is + compressed/extracted, it can ignore events that + are not of type . + + + + + Gets the name of the file being processed. (The name of the file within the Archive; not the external + file path.) Also includes the internal path of the file, if any. Valid for + , , + and messages. + + The name of the file currently being processed, or null if processing + is currently at the stream or archive level. + + + + Gets the number of the current file being processed. The first file is number 0, and the last file + is -1. Valid for , + , and messages. + + The number of the file currently being processed, or the most recent + file processed if processing is currently at the stream or archive level. + + + + Gets the total number of files to be processed. Valid for all message types. + + The total number of files to be processed that are known so far. + + + + Gets the number of bytes processed so far when compressing or extracting a file. Valid for + , , + and messages. + + The number of uncompressed bytes processed so far for the current file, + or 0 if processing is currently at the stream or archive level. + + + + Gets the total number of bytes in the current file. Valid for , + , and messages. + + The uncompressed size of the current file being processed, + or 0 if processing is currently at the stream or archive level. + + + + Gets the name of the current archive. Not necessarily the name of the archive on disk. + Valid for all message types. + + The name of the current archive, or an empty string if no name was specified. + + + + Gets the current archive number, when processing a chained set of archives. Valid for all message types. + + The number of the current archive. + The first archive is number 0, and the last archive is + -1. + + + + Gets the total number of known archives in a chained set. Valid for all message types. + + The total number of known archives in a chained set. + + When using the compression option to auto-split into multiple archives based on data size, + this value will not be accurate until the end. + + + + + Gets the number of compressed bytes processed so far during extraction + of the current archive. Valid for all extraction messages. + + The number of compressed bytes processed so far during extraction + of the current archive. + + + + Gets the total number of compressed bytes to be processed during extraction + of the current archive. Valid for all extraction messages. + + The total number of compressed bytes to be processed during extraction + of the current archive. + + + + Gets the number of uncompressed bytes processed so far among all files. Valid for all message types. + + The number of uncompressed file bytes processed so far among all files. + + When compared to , this can be used as a measure of overall progress. + + + + + Gets the total number of uncompressed file bytes to be processed. Valid for all message types. + + The total number of uncompressed bytes to be processed among all files. + + + + The type of progress event. + + +

PACKING EXAMPLE: The following sequence of events might be received when + extracting a simple archive file with 2 files.

+ + Message TypeDescription + StartArchive Begin extracting archive + StartFile Begin extracting first file + PartialFile Extracting first file + PartialFile Extracting first file + FinishFile Finished extracting first file + StartFile Begin extracting second file + PartialFile Extracting second file + FinishFile Finished extracting second file + FinishArchiveFinished extracting archive + +

+

UNPACKING EXAMPLE: Packing 3 files into 2 archive chunks, where the second file is + continued to the second archive chunk.

+ + Message TypeDescription + StartFile Begin compressing first file + FinishFile Finished compressing first file + StartFile Begin compressing second file + PartialFile Compressing second file + PartialFile Compressing second file + FinishFile Finished compressing second file + StartArchive Begin writing first archive + PartialArchiveWriting first archive + FinishArchive Finished writing first archive + StartFile Begin compressing third file + PartialFile Compressing third file + FinishFile Finished compressing third file + StartArchive Begin writing second archive + PartialArchiveWriting second archive + FinishArchive Finished writing second archive + +
+
+ + Status message before beginning the packing or unpacking an individual file. + + + Status message (possibly reported multiple times) during the process of packing or unpacking a file. + + + Status message after completion of the packing or unpacking an individual file. + + + Status message before beginning the packing or unpacking an archive. + + + Status message (possibly reported multiple times) during the process of packing or unpacking an archiv. + + + Status message after completion of the packing or unpacking of an archive. + + + + Provides a basic implementation of the archive pack and unpack stream context + interfaces, based on a list of archive files, a default directory, and an + optional mapping from internal to external file paths. + + + This class can also handle creating or extracting chained archive packages. + + + + + This interface provides the methods necessary for the + to open and close streams for archives + and files. The implementor of this interface can use any kind of logic + to determine what kind of streams to open and where. + + + + + Gets the name of the archive with a specified number. + + The 0-based index of the archive + within the chain. + The name of the requested archive. May be an empty string + for non-chained archives, but may never be null. + The archive name is the name stored within the archive, used for + identification of the archive especially among archive chains. That + name is often, but not necessarily the same as the filename of the + archive package. + + + + Opens a stream for writing an archive package. + + The 0-based index of the archive within + the chain. + The name of the archive that was returned + by . + True if the stream should be truncated when + opened (if it already exists); false if an existing stream is being + re-opened for writing additional data. + Instance of the compression engine + doing the operations. + A writable Stream where the compressed archive bytes will be + written, or null to cancel the archive creation. + + If this method returns null, the archive engine will throw a + FileNotFoundException. + + + + + Closes a stream where an archive package was written. + + The 0-based index of the archive within + the chain. + The name of the archive that was previously + returned by + . + A stream that was previously returned by + and is now ready to be closed. + + If there is another archive package in the chain, then after this stream + is closed a new stream will be opened. + + + + + Opens a stream to read a file that is to be included in an archive. + + The path of the file within the archive. This is often, + but not necessarily, the same as the relative path of the file outside + the archive. + Returned attributes of the opened file, to be + stored in the archive. + Returned last-modified time of the opened file, + to be stored in the archive. + A readable Stream where the file bytes will be read from before + they are compressed, or null to skip inclusion of the file and continue to + the next file. + + + + Closes a stream that has been used to read a file. + + The path of the file within the archive; the same as + the path provided + when the stream was opened. + A stream that was previously returned by + and is now ready to be closed. + + + + Gets extended parameter information specific to the compression + format being used. + + Name of the option being requested. + Parameters for the option; for per-file options, + the first parameter is typically the internal file path. + Option value, or null to use the default behavior. + + This method provides a way to set uncommon options during packaging, or a + way to handle aspects of compression formats not supported by the base library. + For example, this may be used by the zip compression library to + specify different compression methods/levels on a per-file basis. + The available option names, parameters, and expected return values + should be documented by each compression library. + + + + + This interface provides the methods necessary for the to open + and close streams for archives and files. The implementor of this interface can use any + kind of logic to determine what kind of streams to open and where + + + + + Opens the archive stream for reading. + + The zero-based index of the archive to open. + The name of the archive being opened. + Instance of the compression engine doing the operations. + A stream from which archive bytes are read, or null to cancel extraction + of the archive. + + When the first archive in a chain is opened, the name is not yet known, so the + provided value will be an empty string. When opening further archives, the + provided value is the next-archive name stored in the previous archive. This + name is often, but not necessarily, the same as the filename of the archive + package to be opened. + If this method returns null, the archive engine will throw a + FileNotFoundException. + + + + + Closes a stream where an archive package was read. + + The archive number of the stream to close. + The name of the archive being closed. + The stream that was previously returned by + and is now ready to be closed. + + + + Opens a stream for writing extracted file bytes. + + The path of the file within the archive. This is often, but + not necessarily, the same as the relative path of the file outside the archive. + The uncompressed size of the file to be extracted. + The last write time of the file to be extracted. + A stream where extracted file bytes are to be written, or null to skip + extraction of the file and continue to the next file. + + The implementor may use the path, size and date information to dynamically + decide whether or not the file should be extracted. + + + + + Closes a stream where an extracted file was written. + + The path of the file within the archive. + The stream that was previously returned by + and is now ready to be closed. + The attributes of the extracted file. + The last write time of the file. + + The implementor may wish to apply the attributes and date to the newly-extracted file. + + + + + Creates a new ArchiveFileStreamContext with a archive file and + no default directory or file mapping. + + The path to a archive file that will be + created or extracted. + + + + Creates a new ArchiveFileStreamContext with a archive file, default + directory and mapping from internal to external file paths. + + The path to a archive file that will be + created or extracted. + The default root directory where files will be + located, optional. + A mapping from internal file paths to external file + paths, optional. + + If the mapping is not null and a file is not included in the mapping, + the file will be skipped. + If the external path in the mapping is a simple file name or + relative file path, it will be concatenated onto the default directory, + if one was specified. + For more about how the default directory and files mapping are + used, see and + . + + + + + Creates a new ArchiveFileStreamContext with a list of archive files, + a default directory and a mapping from internal to external file paths. + + A list of paths to archive files that will be + created or extracted. + The default root directory where files will be + located, optional. + A mapping from internal file paths to external file + paths, optional. + + When creating chained archives, the list + should include at least enough archives to handle the entire set of + input files, based on the maximum archive size that is passed to the + .. + If the mapping is not null and a file is not included in the mapping, + the file will be skipped. + If the external path in the mapping is a simple file name or + relative file path, it will be concatenated onto the default directory, + if one was specified. + For more about how the default directory and files mapping are used, + see and + . + + + + + Gets the name of the archive with a specified number. + + The 0-based index of the archive within + the chain. + The name of the requested archive. May be an empty string + for non-chained archives, but may never be null. + This method returns the file name of the archive from the + list with the specified index, or an empty + string if the archive number is outside the bounds of the list. The + file name should not include any directory path. + + + + Opens a stream for writing an archive. + + The 0-based index of the archive within + the chain. + The name of the archive that was returned + by . + True if the stream should be truncated when + opened (if it already exists); false if an existing stream is being + re-opened for writing additional data. + Instance of the compression engine + doing the operations. + A writable Stream where the compressed archive bytes will be + written, or null to cancel the archive creation. + + This method opens the file from the list + with the specified index. If the archive number is outside the bounds + of the list, this method returns null. + If the flag is set, this method + will seek to the start of any existing archive in the file, or to the + end of the file if the existing file is not an archive. + + + + + Closes a stream where an archive package was written. + + The 0-based index of the archive within + the chain. + The name of the archive that was previously + returned by . + A stream that was previously returned by + and is now ready to be closed. + + + + Opens a stream to read a file that is to be included in an archive. + + The path of the file within the archive. + The returned attributes of the opened file, + to be stored in the archive. + The returned last-modified time of the + opened file, to be stored in the archive. + A readable Stream where the file bytes will be read from + before they are compressed, or null to skip inclusion of the file and + continue to the next file. + + This method opens a file using the following logic: + + If the and the mapping + are both null, the path is treated as relative to the current directory, + and that file is opened. + If the is not null but the + mapping is null, the path is treated as relative to that directory, and + that file is opened. + If the is null but the + mapping is not null, the path parameter is used as a key into the mapping, + and the resulting value is the file path that is opened, relative to the + current directory (or it may be an absolute path). If no mapping exists, + the file is skipped. + If both the and the + mapping are specified, the path parameter is used as a key into the + mapping, and the resulting value is the file path that is opened, relative + to the specified directory (or it may be an absolute path). If no mapping + exists, the file is skipped. + + + + + + Closes a stream that has been used to read a file. + + The path of the file within the archive; the same as + the path provided when the stream was opened. + A stream that was previously returned by + and is now ready to be closed. + + + + Gets extended parameter information specific to the compression format + being used. + + Name of the option being requested. + Parameters for the option; for per-file options, + the first parameter is typically the internal file path. + Option value, or null to use the default behavior. + + This implementation does not handle any options. Subclasses may override + this method to allow for non-default behavior. + + + + + Opens the archive stream for reading. + + The zero-based index of the archive to + open. + The name of the archive being opened. + Instance of the compression engine + doing the operations. + A stream from which archive bytes are read, or null to cancel + extraction of the archive. + + This method opens the file from the list with + the specified index. If the archive number is outside the bounds of the + list, this method returns null. + If the flag is set, this method will + seek to the start of any existing archive in the file, or to the end of + the file if the existing file is not an archive. + + + + + Closes a stream where an archive was read. + + The archive number of the stream + to close. + The name of the archive being closed. + The stream that was previously returned by + and is now ready to be closed. + + + + Opens a stream for writing extracted file bytes. + + The path of the file within the archive. + The uncompressed size of the file to be + extracted. + The last write time of the file to be + extracted. + A stream where extracted file bytes are to be written, or null + to skip extraction of the file and continue to the next file. + + This method opens a file using the following logic: + + If the and the mapping + are both null, the path is treated as relative to the current directory, + and that file is opened. + If the is not null but the + mapping is null, the path is treated as relative to that directory, and + that file is opened. + If the is null but the + mapping is not null, the path parameter is used as a key into the mapping, + and the resulting value is the file path that is opened, relative to the + current directory (or it may be an absolute path). If no mapping exists, + the file is skipped. + If both the and the + mapping are specified, the path parameter is used as a key into the + mapping, and the resulting value is the file path that is opened, + relative to the specified directory (or it may be an absolute path). + If no mapping exists, the file is skipped. + + If the flag is set, the file + is skipped if a file currently exists in the same path with an equal + or newer write time. + + + + + Closes a stream where an extracted file was written. + + The path of the file within the archive. + The stream that was previously returned by + and is now ready to be closed. + The attributes of the extracted file. + The last write time of the file. + + After closing the extracted file stream, this method applies the date + and attributes to that file. + + + + + Translates an internal file path to an external file path using the + and the mapping, according to + rules documented in and + . + + The path of the file with the archive. + The external path of the file, or null if there is no + valid translation. + + + + Gets or sets the list of archive files that are created or extracted. + + The list of archive files that are created or extracted. + + + + Gets or sets the default root directory where files are located. + + The default root directory where files are located. + + For details about how the default directory is used, + see and . + + + + + Gets or sets the mapping from internal file paths to external file paths. + + A mapping from internal file paths to external file paths. + + For details about how the files mapping is used, + see and . + + + + + Gets or sets a flag that can prevent extracted files from overwriting + newer files that already exist. + + True to prevent overwriting newer files that already exist + during extraction; false to always extract from the archive regardless + of existing files. + + + + Gets or sets a flag that enables creating or extracting an archive + at an offset within an existing file. (This is typically used to open + archive-based self-extracting packages.) + + True to search an existing package file for an archive offset + or the end of the file;/ false to always create or open a plain + archive file. + + + + Stream context used to extract a single file from an archive into a memory stream. + + + + + Creates a new BasicExtractStreamContext that reads from the specified archive stream. + + Archive stream to read from. + + + + Opens the archive stream for reading. Returns a DuplicateStream instance, + so the stream may be virtually opened multiple times. + + The archive number to open (ignored; 0 is assumed). + The name of the archive being opened. + Instance of the compression engine doing the operations. + A stream from which archive bytes are read. + + + + Does *not* close the stream. The archive stream should be managed by + the code that invokes the archive extraction. + + The archive number of the stream to close. + The name of the archive being closed. + The stream being closed. + + + + Opens a stream for writing extracted file bytes. The returned stream is a MemoryStream + instance, so the file is extracted straight into memory. + + Path of the file within the archive. + The uncompressed size of the file to be extracted. + The last write time of the file. + A stream where extracted file bytes are to be written. + + + + Does *not* close the file stream. The file stream is saved in memory so it can + be read later. + + Path of the file within the archive. + The file stream to be closed. + The attributes of the extracted file. + The last write time of the file. + + + + Gets the stream for the extracted file, or null if no file was extracted. + + + + + Base class for an engine capable of packing and unpacking a particular + compressed file format. + + + + + Creates a new instance of the compression engine base class. + + + + + Disposes the compression engine. + + + + + Disposes of resources allocated by the compression engine. + + + + + Creates an archive. + + A context interface to handle opening + and closing of archive and file streams. + The paths of the files in the archive + (not external file paths). + The archive could not be + created. + + The stream context implementation may provide a mapping from the + file paths within the archive to the external file paths. + + + + + Creates an archive or chain of archives. + + A context interface to handle opening + and closing of archive and file streams. + The paths of the files in the archive (not + external file paths). + The maximum number of bytes for one + archive before the contents are chained to the next archive, or zero + for unlimited archive size. + The archive could not be + created. + + The stream context implementation may provide a mapping from the file + paths within the archive to the external file paths. + + + + + Checks whether a Stream begins with a header that indicates + it is a valid archive. + + Stream for reading the archive file. + True if the stream is a valid archive + (with no offset); false otherwise. + + + + Gets the offset of an archive that is positioned 0 or more bytes + from the start of the Stream. + + A stream for reading the archive. + The offset in bytes of the archive, + or -1 if no archive is found in the Stream. + The archive must begin on a 4-byte boundary. + + + + Gets information about all files in an archive stream. + + A stream for reading the archive. + Information about all files in the archive stream. + The stream is not a valid + archive. + + + + Gets information about files in an archive or archive chain. + + A context interface to handle opening + and closing of archive and file streams. + A predicate that can determine + which files to process, optional. + Information about files in the archive stream. + The archive provided + by the stream context is not valid. + + The predicate takes an internal file + path and returns true to include the file or false to exclude it. + + + + + Gets the list of files in an archive Stream. + + A stream for reading the archive. + A list of the paths of all files contained in the + archive. + The stream is not a valid + archive. + + + + Gets the list of files in an archive or archive chain. + + A context interface to handle opening + and closing of archive and file streams. + A predicate that can determine + which files to process, optional. + An array containing the names of all files contained in + the archive or archive chain. + The archive provided + by the stream context is not valid. + + The predicate takes an internal file + path and returns true to include the file or false to exclude it. + + + + + Reads a single file from an archive stream. + + A stream for reading the archive. + The path of the file within the archive + (not the external file path). + A stream for reading the extracted file, or null + if the file does not exist in the archive. + The stream is not a valid + archive. + The entire extracted file is cached in memory, so this + method requires enough free memory to hold the file. + + + + Extracts files from an archive or archive chain. + + A context interface to handle opening + and closing of archive and file streams. + An optional predicate that can determine + which files to process. + The archive provided + by the stream context is not valid. + + The predicate takes an internal file + path and returns true to include the file or false to exclude it. + + + + + Called by sublcasses to distribute a packing or unpacking progress + event to listeners. + + Event details. + + + + Disposes of resources allocated by the compression engine. + + If true, the method has been called + directly or indirectly by a user's code, so managed and unmanaged + resources will be disposed. If false, the method has been called by + the runtime from inside the finalizer, and only unmanaged resources + will be disposed. + + + + Compresion utility function for converting old-style + date and time values to a DateTime structure. + + + + + Compresion utility function for converting a DateTime structure + to old-style date and time values. + + + + + Occurs when the compression engine reports progress in packing + or unpacking an archive. + + + + + + Gets or sets a flag indicating whether temporary files are created + and used during compression. + + True if temporary files are used; false if compression is done + entirely in-memory. + The value of this property is true by default. Using temporary + files can greatly reduce the memory requirement of compression, + especially when compressing large archives. However, setting this property + to false may yield slightly better performance when creating small + archives. Or it may be necessary if the process does not have sufficient + privileges to create temporary files. + + + + Compression level to use when compressing files. + + A compression level ranging from minimum to maximum compression, + or no compression. + + + + Specifies the compression level ranging from minimum compresion to + maximum compression, or no compression at all. + + + Although only four values are enumerated, any integral value between + and can also be used. + + + + Do not compress files, only store. + + + Minimum compression; fastest. + + + A compromize between speed and compression efficiency. + + + Maximum compression; slowest. + + + + Wraps a source stream and carries additional items that are disposed when the stream is closed. + + + + + Creates a new a cargo stream. + + source of the stream + List of additional items that are disposed when the stream is closed. + The order of the list is the order in which the items are disposed. + + + + Flushes the source stream. + + + + + Sets the length of the source stream. + + The desired length of the stream in bytes. + + + + Closes the source stream and also closes the additional objects that are carried. + + + + + Reads from the source stream. + + An array of bytes. When this method returns, the buffer + contains the specified byte array with the values between offset and + (offset + count - 1) replaced by the bytes read from the source. + The zero-based byte offset in buffer at which to begin + storing the data read from the stream. + The maximum number of bytes to be read from the stream. + The total number of bytes read into the buffer. This can be less + than the number of bytes requested if that many bytes are not currently available, + or zero (0) if the end of the stream has been reached. + + + + Writes to the source stream. + + An array of bytes. This method copies count + bytes from buffer to the stream. + The zero-based byte offset in buffer at which + to begin copying bytes to the stream. + The number of bytes to be written to the stream. + + + + Changes the position of the source stream. + + A byte offset relative to the origin parameter. + A value of type SeekOrigin indicating the reference + point used to obtain the new position. + The new position within the stream. + + + + Gets the source stream of the cargo stream. + + + + + Gets the list of additional items that are disposed when the stream is closed. + The order of the list is the order in which the items are disposed. The contents can be modified any time. + + + + + Gets a value indicating whether the source stream supports reading. + + true if the stream supports reading; otherwise, false. + + + + Gets a value indicating whether the source stream supports writing. + + true if the stream supports writing; otherwise, false. + + + + Gets a value indicating whether the source stream supports seeking. + + true if the stream supports seeking; otherwise, false. + + + + Gets the length of the source stream. + + + + + Gets or sets the position of the source stream. + + + + + Duplicates a source stream by maintaining a separate position. + + + WARNING: duplicate streams are not thread-safe with respect to each other or the original stream. + If multiple threads use duplicate copies of the same stream, they must synchronize for any operations. + + + + + Creates a new duplicate of a stream. + + source of the duplicate + + + + Retrieves the original stream from a possible duplicate stream. + + Possible duplicate stream. + If the stream is a DuplicateStream, returns + the duplicate's source; otherwise returns the same stream. + + + + Flushes the source stream. + + + + + Sets the length of the source stream. + + The desired length of the stream in bytes. + + + + Closes the underlying stream, effectively closing ALL duplicates. + + + + + Reads from the source stream while maintaining a separate position + and not impacting the source stream's position. + + An array of bytes. When this method returns, the buffer + contains the specified byte array with the values between offset and + (offset + count - 1) replaced by the bytes read from the current source. + The zero-based byte offset in buffer at which to begin + storing the data read from the current stream. + The maximum number of bytes to be read from the current stream. + The total number of bytes read into the buffer. This can be less + than the number of bytes requested if that many bytes are not currently available, + or zero (0) if the end of the stream has been reached. + + + + Writes to the source stream while maintaining a separate position + and not impacting the source stream's position. + + An array of bytes. This method copies count + bytes from buffer to the current stream. + The zero-based byte offset in buffer at which + to begin copying bytes to the current stream. + The number of bytes to be written to the + current stream. + + + + Changes the position of this stream without impacting the + source stream's position. + + A byte offset relative to the origin parameter. + A value of type SeekOrigin indicating the reference + point used to obtain the new position. + The new position within the current stream. + + + + Gets the original stream that was used to create the duplicate. + + + + + Gets a value indicating whether the source stream supports reading. + + true if the stream supports reading; otherwise, false. + + + + Gets a value indicating whether the source stream supports writing. + + true if the stream supports writing; otherwise, false. + + + + Gets a value indicating whether the source stream supports seeking. + + true if the stream supports seeking; otherwise, false. + + + + Gets the length of the source stream. + + + + + Gets or sets the position of the current stream, + ignoring the position of the source stream. + + + + + Wraps a source stream and offsets all read/write/seek calls by a given value. + + + This class is used to trick archive an packing or unpacking process + into reading or writing at an offset into a file, primarily for + self-extracting packages. + + + + + Creates a new OffsetStream instance from a source stream + and using a specified offset. + + Underlying stream for which all calls will be offset. + Positive or negative number of bytes to offset. + + + + Reads a sequence of bytes from the source stream and advances + the position within the stream by the number of bytes read. + + An array of bytes. When this method returns, the buffer + contains the specified byte array with the values between offset and + (offset + count - 1) replaced by the bytes read from the current source. + The zero-based byte offset in buffer at which to begin + storing the data read from the current stream. + The maximum number of bytes to be read from the current stream. + The total number of bytes read into the buffer. This can be less + than the number of bytes requested if that many bytes are not currently available, + or zero (0) if the end of the stream has been reached. + + + + Writes a sequence of bytes to the source stream and advances the + current position within this stream by the number of bytes written. + + An array of bytes. This method copies count + bytes from buffer to the current stream. + The zero-based byte offset in buffer at which + to begin copying bytes to the current stream. + The number of bytes to be written to the + current stream. + + + + Reads a byte from the stream and advances the position within the + source stream by one byte, or returns -1 if at the end of the stream. + + The unsigned byte cast to an Int32, or -1 if at the + end of the stream. + + + + Writes a byte to the current position in the source stream and + advances the position within the stream by one byte. + + The byte to write to the stream. + + + + Flushes the source stream. + + + + + Sets the position within the current stream, which is + equal to the position within the source stream minus the offset. + + A byte offset relative to the origin parameter. + A value of type SeekOrigin indicating + the reference point used to obtain the new position. + The new position within the current stream. + + + + Sets the effective length of the stream, which is equal to + the length of the source stream minus the offset. + + The desired length of the + current stream in bytes. + + + + Closes the underlying stream. + + + + + Gets the underlying stream that this OffsetStream calls into. + + + + + Gets the number of bytes to offset all calls before + redirecting to the underlying stream. + + + + + Gets a value indicating whether the source stream supports reading. + + true if the stream supports reading; otherwise, false. + + + + Gets a value indicating whether the source stream supports writing. + + true if the stream supports writing; otherwise, false. + + + + Gets a value indicating whether the source stream supports seeking. + + true if the stream supports seeking; otherwise, false. + + + + Gets the effective length of the stream, which is equal to + the length of the source stream minus the offset. + + + + + Gets or sets the effective position of the stream, which + is equal to the position of the source stream minus the offset. + + + + + Distribution specific strings. + + + + + News URL for the distribution. + + + + + Short product name for the distribution. + + + + + Support URL for the distribution. + + + + + Telemetry URL format for the distribution. + + +
+
diff --git a/TemplatePackageFix/TemplatePackageFix.csproj b/TemplatePackageFix/TemplatePackageFix.csproj new file mode 100644 index 0000000..3c1ec03 --- /dev/null +++ b/TemplatePackageFix/TemplatePackageFix.csproj @@ -0,0 +1,114 @@ + + + + + Debug + AnyCPU + {71E359DE-5694-43B6-BB0A-F64E796E1655} + Exe + Properties + Plumsail.TemplatePackageFix + TemplatePackageFix + v4.5 + 512 + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 1 + 1.0.0.%2a + false + true + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + Plumsail.TemplatePackageFix.Program + + + 7E2FE55F33810568A0571C1C9C199196AEF24CA9 + + + TemplatePackageFix_TemporaryKey.pfx + + + true + + + true + + + + Reference\Microsoft.Deployment.Compression.dll + + + Reference\Microsoft.Deployment.Compression.Cab.dll + + + + + + + + + + + + + + + + + + + + False + Microsoft .NET Framework 4.5 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + + + + + + \ No newline at end of file diff --git a/TemplatePackageFixSolution.sln b/TemplatePackageFixSolution.sln new file mode 100644 index 0000000..423990b --- /dev/null +++ b/TemplatePackageFixSolution.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.30723.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TemplatePackageFix", "TemplatePackageFix\TemplatePackageFix.csproj", "{71E359DE-5694-43B6-BB0A-F64E796E1655}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {71E359DE-5694-43B6-BB0A-F64E796E1655}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {71E359DE-5694-43B6-BB0A-F64E796E1655}.Debug|Any CPU.Build.0 = Debug|Any CPU + {71E359DE-5694-43B6-BB0A-F64E796E1655}.Release|Any CPU.ActiveCfg = Release|Any CPU + {71E359DE-5694-43B6-BB0A-F64E796E1655}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal