├── .gitattributes ├── .gitignore ├── App.config ├── CabMaker-icon-256x256.ico ├── CabMaker-icon-256x256.png ├── CabMaker.csproj ├── CabMaker.sln ├── CompressionWindowSize.cs ├── Constants.cs ├── DdfBuilder.cs ├── DdfFileRow.cs ├── EnumUtil.cs ├── Enums.cs ├── IsolatedStorageExtensions.cs ├── MainForm.Designer.cs ├── MainForm.cs ├── MainForm.resx ├── Program.cs ├── Properties ├── AssemblyInfo.cs ├── Resources.Designer.cs ├── Resources.resx ├── Settings.Designer.cs └── Settings.settings ├── README.md ├── StringExtensions.cs └── UserSettings.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /CabMaker-icon-256x256.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapientcoder/CabMaker/93c684c6e3ee371bc3ac5f94e592a022a7aa9f54/CabMaker-icon-256x256.ico -------------------------------------------------------------------------------- /CabMaker-icon-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapientcoder/CabMaker/93c684c6e3ee371bc3ac5f94e592a022a7aa9f54/CabMaker-icon-256x256.png -------------------------------------------------------------------------------- /CabMaker.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {5D270624-B71E-43CE-BD48-2C504DA2A101} 8 | WinExe 9 | Properties 10 | CabMaker 11 | CabMaker 12 | v4.8 13 | 512 14 | true 15 | false 16 | publish\ 17 | true 18 | Disk 19 | false 20 | Foreground 21 | 7 22 | Days 23 | false 24 | false 25 | true 26 | 0 27 | 1.0.0.%2a 28 | false 29 | true 30 | 31 | 32 | 33 | AnyCPU 34 | true 35 | full 36 | false 37 | bin\Debug\ 38 | DEBUG;TRACE 39 | prompt 40 | 4 41 | false 42 | 43 | 44 | AnyCPU 45 | pdbonly 46 | true 47 | bin\Release\ 48 | TRACE 49 | prompt 50 | 4 51 | false 52 | 53 | 54 | CabMaker-icon-256x256.ico 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | Form 78 | 79 | 80 | MainForm.cs 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | MainForm.cs 89 | 90 | 91 | ResXFileCodeGenerator 92 | Resources.Designer.cs 93 | Designer 94 | 95 | 96 | True 97 | Resources.resx 98 | True 99 | 100 | 101 | SettingsSingleFileGenerator 102 | Settings.Designer.cs 103 | 104 | 105 | True 106 | Settings.settings 107 | True 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | False 116 | Microsoft .NET Framework 4.6 %28x86 and x64%29 117 | true 118 | 119 | 120 | False 121 | .NET Framework 3.5 SP1 122 | false 123 | 124 | 125 | 126 | 127 | 128 | 129 | 136 | -------------------------------------------------------------------------------- /CabMaker.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.4.33213.308 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CabMaker", "CabMaker.csproj", "{5D270624-B71E-43CE-BD48-2C504DA2A101}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {5D270624-B71E-43CE-BD48-2C504DA2A101}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {5D270624-B71E-43CE-BD48-2C504DA2A101}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {5D270624-B71E-43CE-BD48-2C504DA2A101}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {5D270624-B71E-43CE-BD48-2C504DA2A101}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {AC8061B7-A970-4C67-8ACB-015A393DA731} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /CompressionWindowSize.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CabMaker 4 | { 5 | [Serializable] 6 | public class CompressionWindowSize 7 | { 8 | public CompressionWindowSize(int exponent, string size) 9 | { 10 | Exponent = exponent; 11 | Size = size; 12 | } 13 | 14 | public int Exponent { get; set; } 15 | public string Size { get; set; } 16 | public string Description => $"{Exponent} ({Size})"; 17 | 18 | public override string ToString() 19 | { 20 | return $"{Exponent} ({Description})"; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Constants.cs: -------------------------------------------------------------------------------- 1 | namespace CabMaker 2 | { 3 | public static class Constants 4 | { 5 | public static CompressionType DefaultCompressionType = CompressionType.MSZIP; 6 | public static CompressionWindowSize DefaultCompressionWindowSize; 7 | 8 | static Constants() 9 | { 10 | DefaultCompressionWindowSize = CompressionWindowSizes[3]; 11 | } 12 | 13 | /// 14 | /// Size of the LZX sliding window. 15 | /// 16 | /// 17 | public static CompressionWindowSize[] CompressionWindowSizes = new [] 18 | { 19 | new CompressionWindowSize(15, "32 KB"), // 2^15 20 | new CompressionWindowSize(16, "64 KB"), // 2^16 21 | new CompressionWindowSize(17, "128 KB"), // etc. 22 | new CompressionWindowSize(18, "256 KB"), 23 | new CompressionWindowSize(19, "512 KB"), 24 | new CompressionWindowSize(20, "1 MB"), 25 | new CompressionWindowSize(21, "2 MB") 26 | }; 27 | 28 | public const int MaxLinesInDdf = 1024; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /DdfBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace CabMaker 8 | { 9 | /// 10 | /// Utility class for building a DDF file. 11 | /// 12 | internal class DdfFileBuilder 13 | { 14 | string _sourceFolder; 15 | bool _isRecursive; 16 | string _targetFolder; 17 | string _targetFileName; 18 | CompressionType _compressionType = Constants.DefaultCompressionType; 19 | CompressionWindowSize _compressionWindowSize; 20 | 21 | public DdfFileBuilder( 22 | string sourceFolder, 23 | bool isRecursive, 24 | string targetFolder, 25 | string targetFileName, 26 | CompressionType compressionType, 27 | CompressionWindowSize compressionWindowSize) 28 | { 29 | _isRecursive = isRecursive; 30 | 31 | if (string.IsNullOrWhiteSpace(sourceFolder)) 32 | throw new ArgumentException($"{nameof(sourceFolder)} cannot be empty."); 33 | 34 | if (string.IsNullOrWhiteSpace(targetFolder)) 35 | throw new ArgumentException($"{nameof(targetFolder)} cannot be empty."); 36 | 37 | if (string.IsNullOrWhiteSpace(targetFileName)) 38 | throw new ArgumentException($"{nameof(targetFileName)} cannot be empty."); 39 | 40 | _sourceFolder = sourceFolder; 41 | _targetFolder = targetFolder; 42 | _targetFileName = targetFileName; 43 | _compressionType = compressionType; 44 | _compressionWindowSize = compressionWindowSize ?? Constants.DefaultCompressionWindowSize; 45 | 46 | DdfFilePath = Path.Combine(_targetFolder, targetFileName + ".ddf"); 47 | } 48 | 49 | /// 50 | /// Gets the full path of the DDF file. 51 | /// 52 | public string DdfFilePath { get; private set; } 53 | 54 | /// 55 | /// Builds the DDF file and saves it to disk. 56 | /// 57 | public void BuildAndSave() 58 | { 59 | bool compress = _compressionType != CompressionType.None; 60 | string compressValue = compress ? "on" : "off"; 61 | 62 | StringBuilder ddf = new StringBuilder(); 63 | ddf.AppendLine($@";*** MakeCAB Directive file; 64 | .OPTION EXPLICIT 65 | .Set CabinetNameTemplate={_targetFileName.EnsureQuoted()} 66 | .Set DiskDirectory1={_targetFolder.EnsureQuoted()} 67 | .Set MaxDiskSize=0 68 | .Set Cabinet=on 69 | .Set Compress={compressValue}"); 70 | 71 | if (compress) 72 | { 73 | ddf.AppendLine($".Set CompressionType={_compressionType}"); 74 | } 75 | 76 | ddf.AppendLine(); 77 | 78 | if (IsCompressionWindowSizeIncluded(_compressionType)) 79 | { 80 | ddf.AppendFormat($".Set CompressionMemory={(_compressionWindowSize).Exponent}"); 81 | ddf.AppendLine(); 82 | } 83 | 84 | int ddfHeaderLines = ddf.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Length; 85 | int maxFiles = Constants.MaxLinesInDdf - ddfHeaderLines; // only write enough files to hit the max # of lines allowed in a DDF (blank lines don't count) 86 | 87 | List ddfFiles = GetFiles(_sourceFolder); 88 | 89 | foreach (var ddfFile in ddfFiles.Take(maxFiles)) 90 | { 91 | ddf.AppendFormat("\"{0}\" \"{1}\"{2}", ddfFile.FullName, ddfFile.Path, Environment.NewLine); 92 | } 93 | 94 | File.WriteAllText(DdfFilePath, ddf.ToString(), Encoding.Default); 95 | } 96 | 97 | public static bool IsCompressionWindowSizeIncluded(CompressionType compressionType) 98 | { 99 | return compressionType != CompressionType.None && compressionType != Constants.DefaultCompressionType; 100 | } 101 | 102 | List GetFiles(string sDir) 103 | { 104 | List list = new List(); 105 | string srcPath = _sourceFolder; 106 | 107 | foreach (string f in Directory.GetFiles(sDir)) 108 | { 109 | list.Add(new DdfFileRow() 110 | { 111 | FullName = f, 112 | Path = f.Replace(srcPath, "").TrimStart('\\') 113 | }); 114 | } 115 | 116 | if (_isRecursive) 117 | { 118 | foreach (string d in Directory.GetDirectories(sDir)) 119 | { 120 | list.AddRange(GetFiles(d)); 121 | } 122 | } 123 | 124 | return list; 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /DdfFileRow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CabMaker 4 | { 5 | /// 6 | /// Represents one row in a DDF file. 7 | /// 8 | /// 9 | public class DdfFileRow 10 | { 11 | public string FullName { get; set; } 12 | public string Path { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /EnumUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CabMaker 4 | { 5 | /// 6 | /// Utility class for working with enumerations. 7 | /// 8 | internal class EnumUtil 9 | { 10 | public static TEnum SafeParse(string value, TEnum defaultValue) where TEnum : struct 11 | { 12 | TEnum result; 13 | 14 | bool success = Enum.TryParse(value, true, out result); 15 | 16 | return success ? result : defaultValue; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Enums.cs: -------------------------------------------------------------------------------- 1 | namespace CabMaker 2 | { 3 | /// 4 | /// Identifies the compression engine/type. 5 | /// 6 | public enum CompressionType 7 | { 8 | None, 9 | MSZIP, 10 | LZX 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /IsolatedStorageExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.IO.IsolatedStorage; 4 | using System.Runtime.Serialization.Formatters.Binary; 5 | 6 | namespace CabMaker 7 | { 8 | /// 9 | /// Extension methods for working with isolated storage. 10 | /// 11 | public static class IsolatedStorageExtensions 12 | { 13 | /// 14 | /// Saves an object to isolated storage. 15 | /// 16 | /// Isolated storage 17 | /// Object to save 18 | /// File name to which object will be saved 19 | public static void SaveObject(this IsolatedStorage isoStorage, object obj, string fileName) 20 | { 21 | using (IsolatedStorageFileStream writeStream = new IsolatedStorageFileStream(fileName, FileMode.Create)) 22 | { 23 | BinaryFormatter formatter = new BinaryFormatter(); 24 | formatter.Serialize(writeStream, obj); 25 | } 26 | } 27 | 28 | /// 29 | /// Reads an object from isolated storage. 30 | /// 31 | /// Type of object to read 32 | /// Isolated storage 33 | /// File name from which object will be loaded 34 | /// Object read from isolated storage (as type ) 35 | public static T LoadObject(this IsolatedStorage isoStorage, string fileName) 36 | { 37 | try 38 | { 39 | using (IsolatedStorageFileStream readStream = new IsolatedStorageFileStream(fileName, FileMode.Open)) 40 | { 41 | BinaryFormatter formatter = new BinaryFormatter(); 42 | 43 | try 44 | { 45 | T readData = (T)formatter.Deserialize(readStream); 46 | return readData; 47 | } 48 | catch 49 | { 50 | return default(T); 51 | } 52 | } 53 | } 54 | catch (FileNotFoundException) 55 | { 56 | return default(T); 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /MainForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace CabMaker 2 | { 3 | partial class MainForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); 32 | this.label1 = new System.Windows.Forms.Label(); 33 | this.txtSourceFolder = new System.Windows.Forms.TextBox(); 34 | this.btnSourceBrowse = new System.Windows.Forms.Button(); 35 | this.label2 = new System.Windows.Forms.Label(); 36 | this.txtTargetFolder = new System.Windows.Forms.TextBox(); 37 | this.btnTargetBrowse = new System.Windows.Forms.Button(); 38 | this.txtOutput = new System.Windows.Forms.TextBox(); 39 | this.label3 = new System.Windows.Forms.Label(); 40 | this.btnRun = new System.Windows.Forms.Button(); 41 | this.label4 = new System.Windows.Forms.Label(); 42 | this.txtFileName = new System.Windows.Forms.TextBox(); 43 | this.chkRecursive = new System.Windows.Forms.CheckBox(); 44 | this.label5 = new System.Windows.Forms.Label(); 45 | this.chkRemember = new System.Windows.Forms.CheckBox(); 46 | this.lblOutputStatus = new System.Windows.Forms.Label(); 47 | this.label6 = new System.Windows.Forms.Label(); 48 | this.lblVersion = new System.Windows.Forms.Label(); 49 | this.label7 = new System.Windows.Forms.Label(); 50 | this.label8 = new System.Windows.Forms.Label(); 51 | this.cboCompressType = new System.Windows.Forms.ComboBox(); 52 | this.cboCompressMemory = new System.Windows.Forms.ComboBox(); 53 | this.SuspendLayout(); 54 | // 55 | // label1 56 | // 57 | this.label1.AutoSize = true; 58 | this.label1.Location = new System.Drawing.Point(18, 14); 59 | this.label1.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); 60 | this.label1.Name = "label1"; 61 | this.label1.Size = new System.Drawing.Size(108, 20); 62 | this.label1.TabIndex = 0; 63 | this.label1.Text = "Source folder:"; 64 | // 65 | // txtSourceFolder 66 | // 67 | this.txtSourceFolder.Location = new System.Drawing.Point(23, 38); 68 | this.txtSourceFolder.Margin = new System.Windows.Forms.Padding(5); 69 | this.txtSourceFolder.Name = "txtSourceFolder"; 70 | this.txtSourceFolder.Size = new System.Drawing.Size(663, 26); 71 | this.txtSourceFolder.TabIndex = 1; 72 | // 73 | // btnSourceBrowse 74 | // 75 | this.btnSourceBrowse.Location = new System.Drawing.Point(696, 35); 76 | this.btnSourceBrowse.Margin = new System.Windows.Forms.Padding(5); 77 | this.btnSourceBrowse.Name = "btnSourceBrowse"; 78 | this.btnSourceBrowse.Size = new System.Drawing.Size(113, 35); 79 | this.btnSourceBrowse.TabIndex = 2; 80 | this.btnSourceBrowse.Text = "Browse..."; 81 | this.btnSourceBrowse.UseVisualStyleBackColor = true; 82 | this.btnSourceBrowse.Click += new System.EventHandler(this.btnSourceBrowse_Click); 83 | // 84 | // label2 85 | // 86 | this.label2.AutoSize = true; 87 | this.label2.Location = new System.Drawing.Point(18, 138); 88 | this.label2.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); 89 | this.label2.Name = "label2"; 90 | this.label2.Size = new System.Drawing.Size(103, 20); 91 | this.label2.TabIndex = 4; 92 | this.label2.Text = "Target folder:"; 93 | // 94 | // txtTargetFolder 95 | // 96 | this.txtTargetFolder.Location = new System.Drawing.Point(23, 163); 97 | this.txtTargetFolder.Margin = new System.Windows.Forms.Padding(5); 98 | this.txtTargetFolder.Name = "txtTargetFolder"; 99 | this.txtTargetFolder.Size = new System.Drawing.Size(663, 26); 100 | this.txtTargetFolder.TabIndex = 5; 101 | // 102 | // btnTargetBrowse 103 | // 104 | this.btnTargetBrowse.Location = new System.Drawing.Point(696, 162); 105 | this.btnTargetBrowse.Margin = new System.Windows.Forms.Padding(5); 106 | this.btnTargetBrowse.Name = "btnTargetBrowse"; 107 | this.btnTargetBrowse.Size = new System.Drawing.Size(113, 35); 108 | this.btnTargetBrowse.TabIndex = 6; 109 | this.btnTargetBrowse.Text = "Browse..."; 110 | this.btnTargetBrowse.UseVisualStyleBackColor = true; 111 | this.btnTargetBrowse.Click += new System.EventHandler(this.btnTargetBrowse_Click); 112 | // 113 | // txtOutput 114 | // 115 | this.txtOutput.BackColor = System.Drawing.Color.White; 116 | this.txtOutput.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 117 | this.txtOutput.Location = new System.Drawing.Point(23, 469); 118 | this.txtOutput.Margin = new System.Windows.Forms.Padding(5); 119 | this.txtOutput.Multiline = true; 120 | this.txtOutput.Name = "txtOutput"; 121 | this.txtOutput.ReadOnly = true; 122 | this.txtOutput.ScrollBars = System.Windows.Forms.ScrollBars.Both; 123 | this.txtOutput.Size = new System.Drawing.Size(784, 329); 124 | this.txtOutput.TabIndex = 13; 125 | // 126 | // label3 127 | // 128 | this.label3.AutoSize = true; 129 | this.label3.Location = new System.Drawing.Point(20, 433); 130 | this.label3.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); 131 | this.label3.Name = "label3"; 132 | this.label3.Size = new System.Drawing.Size(62, 20); 133 | this.label3.TabIndex = 12; 134 | this.label3.Text = "Output:"; 135 | // 136 | // btnRun 137 | // 138 | this.btnRun.Location = new System.Drawing.Point(696, 425); 139 | this.btnRun.Margin = new System.Windows.Forms.Padding(5); 140 | this.btnRun.Name = "btnRun"; 141 | this.btnRun.Size = new System.Drawing.Size(113, 35); 142 | this.btnRun.TabIndex = 11; 143 | this.btnRun.Text = "Make CAB"; 144 | this.btnRun.UseVisualStyleBackColor = true; 145 | this.btnRun.Click += new System.EventHandler(this.btnRun_Click); 146 | // 147 | // label4 148 | // 149 | this.label4.AutoSize = true; 150 | this.label4.Location = new System.Drawing.Point(18, 232); 151 | this.label4.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); 152 | this.label4.Name = "label4"; 153 | this.label4.Size = new System.Drawing.Size(127, 20); 154 | this.label4.TabIndex = 7; 155 | this.label4.Text = "Target file name:"; 156 | // 157 | // txtFileName 158 | // 159 | this.txtFileName.Location = new System.Drawing.Point(23, 257); 160 | this.txtFileName.Margin = new System.Windows.Forms.Padding(5); 161 | this.txtFileName.Name = "txtFileName"; 162 | this.txtFileName.Size = new System.Drawing.Size(355, 26); 163 | this.txtFileName.TabIndex = 8; 164 | // 165 | // chkRecursive 166 | // 167 | this.chkRecursive.AutoSize = true; 168 | this.chkRecursive.Checked = true; 169 | this.chkRecursive.CheckState = System.Windows.Forms.CheckState.Checked; 170 | this.chkRecursive.Location = new System.Drawing.Point(45, 78); 171 | this.chkRecursive.Margin = new System.Windows.Forms.Padding(5); 172 | this.chkRecursive.Name = "chkRecursive"; 173 | this.chkRecursive.Size = new System.Drawing.Size(375, 24); 174 | this.chkRecursive.TabIndex = 3; 175 | this.chkRecursive.Text = "Include all sub-folders beneath the source folder"; 176 | this.chkRecursive.UseVisualStyleBackColor = true; 177 | // 178 | // label5 179 | // 180 | this.label5.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; 181 | this.label5.Location = new System.Drawing.Point(24, 394); 182 | this.label5.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); 183 | this.label5.Name = "label5"; 184 | this.label5.Size = new System.Drawing.Size(785, 3); 185 | this.label5.TabIndex = 10; 186 | // 187 | // chkRemember 188 | // 189 | this.chkRemember.AutoSize = true; 190 | this.chkRemember.Checked = true; 191 | this.chkRemember.CheckState = System.Windows.Forms.CheckState.Checked; 192 | this.chkRemember.Location = new System.Drawing.Point(465, 260); 193 | this.chkRemember.Margin = new System.Windows.Forms.Padding(5); 194 | this.chkRemember.Name = "chkRemember"; 195 | this.chkRemember.Size = new System.Drawing.Size(341, 24); 196 | this.chkRemember.TabIndex = 9; 197 | this.chkRemember.Text = "Remember these values next time app runs"; 198 | this.chkRemember.UseVisualStyleBackColor = true; 199 | // 200 | // lblOutputStatus 201 | // 202 | this.lblOutputStatus.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 203 | this.lblOutputStatus.Location = new System.Drawing.Point(128, 433); 204 | this.lblOutputStatus.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); 205 | this.lblOutputStatus.Name = "lblOutputStatus"; 206 | this.lblOutputStatus.Size = new System.Drawing.Size(560, 26); 207 | this.lblOutputStatus.TabIndex = 14; 208 | this.lblOutputStatus.TextAlign = System.Drawing.ContentAlignment.TopRight; 209 | // 210 | // label6 211 | // 212 | this.label6.AutoSize = true; 213 | this.label6.Location = new System.Drawing.Point(20, 823); 214 | this.label6.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); 215 | this.label6.Name = "label6"; 216 | this.label6.Size = new System.Drawing.Size(67, 20); 217 | this.label6.TabIndex = 15; 218 | this.label6.Text = "Version:"; 219 | // 220 | // lblVersion 221 | // 222 | this.lblVersion.AutoSize = true; 223 | this.lblVersion.Location = new System.Drawing.Point(94, 823); 224 | this.lblVersion.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); 225 | this.lblVersion.Name = "lblVersion"; 226 | this.lblVersion.Size = new System.Drawing.Size(129, 20); 227 | this.lblVersion.TabIndex = 16; 228 | this.lblVersion.Text = "(set at form load)"; 229 | // 230 | // label7 231 | // 232 | this.label7.AutoSize = true; 233 | this.label7.Location = new System.Drawing.Point(20, 333); 234 | this.label7.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); 235 | this.label7.Name = "label7"; 236 | this.label7.Size = new System.Drawing.Size(144, 20); 237 | this.label7.TabIndex = 17; 238 | this.label7.Text = "Compression Type:"; 239 | // 240 | // label8 241 | // 242 | this.label8.AutoSize = true; 243 | this.label8.Location = new System.Drawing.Point(461, 333); 244 | this.label8.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0); 245 | this.label8.Name = "label8"; 246 | this.label8.Size = new System.Drawing.Size(166, 20); 247 | this.label8.TabIndex = 18; 248 | this.label8.Text = "Compression Memory:"; 249 | // 250 | // cboCompressType 251 | // 252 | this.cboCompressType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 253 | this.cboCompressType.FormattingEnabled = true; 254 | this.cboCompressType.Location = new System.Drawing.Point(188, 330); 255 | this.cboCompressType.Name = "cboCompressType"; 256 | this.cboCompressType.Size = new System.Drawing.Size(190, 28); 257 | this.cboCompressType.TabIndex = 19; 258 | this.cboCompressType.SelectedIndexChanged += new System.EventHandler(this.cboCompressType_SelectedIndexChanged); 259 | // 260 | // cboCompressMemory 261 | // 262 | this.cboCompressMemory.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 263 | this.cboCompressMemory.Enabled = false; 264 | this.cboCompressMemory.FormattingEnabled = true; 265 | this.cboCompressMemory.Location = new System.Drawing.Point(647, 330); 266 | this.cboCompressMemory.Name = "cboCompressMemory"; 267 | this.cboCompressMemory.Size = new System.Drawing.Size(162, 28); 268 | this.cboCompressMemory.TabIndex = 20; 269 | // 270 | // MainForm 271 | // 272 | this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); 273 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 274 | this.ClientSize = new System.Drawing.Size(834, 870); 275 | this.Controls.Add(this.cboCompressMemory); 276 | this.Controls.Add(this.cboCompressType); 277 | this.Controls.Add(this.label8); 278 | this.Controls.Add(this.label7); 279 | this.Controls.Add(this.lblVersion); 280 | this.Controls.Add(this.label6); 281 | this.Controls.Add(this.lblOutputStatus); 282 | this.Controls.Add(this.chkRemember); 283 | this.Controls.Add(this.label5); 284 | this.Controls.Add(this.chkRecursive); 285 | this.Controls.Add(this.txtFileName); 286 | this.Controls.Add(this.label4); 287 | this.Controls.Add(this.btnRun); 288 | this.Controls.Add(this.label3); 289 | this.Controls.Add(this.txtOutput); 290 | this.Controls.Add(this.btnTargetBrowse); 291 | this.Controls.Add(this.txtTargetFolder); 292 | this.Controls.Add(this.label2); 293 | this.Controls.Add(this.btnSourceBrowse); 294 | this.Controls.Add(this.txtSourceFolder); 295 | this.Controls.Add(this.label1); 296 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 297 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 298 | this.Margin = new System.Windows.Forms.Padding(5); 299 | this.MaximizeBox = false; 300 | this.Name = "MainForm"; 301 | this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; 302 | this.Text = "CabMaker"; 303 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); 304 | this.Load += new System.EventHandler(this.MainForm_Load); 305 | this.ResumeLayout(false); 306 | this.PerformLayout(); 307 | 308 | } 309 | 310 | #endregion 311 | 312 | private System.Windows.Forms.Label label1; 313 | private System.Windows.Forms.TextBox txtSourceFolder; 314 | private System.Windows.Forms.Button btnSourceBrowse; 315 | private System.Windows.Forms.Label label2; 316 | private System.Windows.Forms.TextBox txtTargetFolder; 317 | private System.Windows.Forms.Button btnTargetBrowse; 318 | private System.Windows.Forms.TextBox txtOutput; 319 | private System.Windows.Forms.Label label3; 320 | private System.Windows.Forms.Button btnRun; 321 | private System.Windows.Forms.Label label4; 322 | private System.Windows.Forms.TextBox txtFileName; 323 | private System.Windows.Forms.CheckBox chkRecursive; 324 | private System.Windows.Forms.Label label5; 325 | private System.Windows.Forms.CheckBox chkRemember; 326 | private System.Windows.Forms.Label lblOutputStatus; 327 | private System.Windows.Forms.Label label6; 328 | private System.Windows.Forms.Label lblVersion; 329 | private System.Windows.Forms.Label label7; 330 | private System.Windows.Forms.Label label8; 331 | private System.Windows.Forms.ComboBox cboCompressType; 332 | private System.Windows.Forms.ComboBox cboCompressMemory; 333 | } 334 | } 335 | 336 | -------------------------------------------------------------------------------- /MainForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Drawing; 4 | using System.IO; 5 | using System.Reflection; 6 | using System.Windows.Forms; 7 | 8 | namespace CabMaker 9 | { 10 | public partial class MainForm : Form 11 | { 12 | private const int EXIT_CODE_SUCCESS = 0; 13 | 14 | public MainForm() 15 | { 16 | InitializeComponent(); 17 | } 18 | 19 | private void btnSourceBrowse_Click(object sender, EventArgs e) 20 | { 21 | FolderBrowserDialog dialog = new FolderBrowserDialog(); 22 | 23 | dialog.SelectedPath = txtSourceFolder.Text; 24 | 25 | if (dialog.ShowDialog() == DialogResult.OK) 26 | { 27 | txtSourceFolder.Text = dialog.SelectedPath; 28 | } 29 | } 30 | 31 | private void btnTargetBrowse_Click(object sender, EventArgs e) 32 | { 33 | FolderBrowserDialog dialog = new FolderBrowserDialog(); 34 | 35 | dialog.SelectedPath = txtTargetFolder.Text; 36 | 37 | if (dialog.ShowDialog() == DialogResult.OK) 38 | { 39 | txtTargetFolder.Text = dialog.SelectedPath; 40 | } 41 | } 42 | 43 | private void btnRun_Click(object sender, EventArgs e) 44 | { 45 | btnRun.Enabled = false; 46 | 47 | lblOutputStatus.Text = ""; 48 | lblOutputStatus.ForeColor = SystemColors.WindowText; 49 | 50 | txtOutput.Clear(); 51 | txtOutput.ForeColor = SystemColors.WindowText; 52 | 53 | if (String.IsNullOrWhiteSpace(txtSourceFolder.Text) || 54 | String.IsNullOrWhiteSpace(txtTargetFolder.Text) || 55 | String.IsNullOrWhiteSpace(txtFileName.Text)) 56 | { 57 | txtOutput.AppendText("Error: Source path, target path, and target file name must be specified."); 58 | txtOutput.ForeColor = Color.Red; 59 | } 60 | else 61 | { 62 | try 63 | { 64 | // Create target folder if it doesn't already exist 65 | 66 | if (!Directory.Exists(txtTargetFolder.Text)) 67 | { 68 | Directory.CreateDirectory(txtTargetFolder.Text); 69 | } 70 | 71 | // Build DDF file 72 | 73 | DdfFileBuilder ddfBuilder = new DdfFileBuilder( 74 | txtSourceFolder.Text, 75 | chkRecursive.Checked, 76 | txtTargetFolder.Text, 77 | txtFileName.Text, 78 | EnumUtil.SafeParse(cboCompressType.SelectedItem as string, Constants.DefaultCompressionType), 79 | cboCompressMemory.SelectedItem as CompressionWindowSize); 80 | 81 | ddfBuilder.BuildAndSave(); 82 | 83 | // Run "makecab.exe" 84 | 85 | string cmd = String.Format("/f {0}", ddfBuilder.DdfFilePath.EnsureQuoted()); 86 | 87 | Process process = new Process(); 88 | 89 | ProcessStartInfo startInfo = new ProcessStartInfo(); 90 | startInfo.CreateNoWindow = true; 91 | startInfo.FileName = "makecab.exe"; 92 | startInfo.Arguments = cmd; 93 | startInfo.RedirectStandardOutput = true; 94 | startInfo.RedirectStandardError = true; 95 | startInfo.UseShellExecute = false; 96 | process.StartInfo = startInfo; 97 | 98 | process.ErrorDataReceived += Process_ErrorDataReceived; 99 | process.OutputDataReceived += Process_OutputDataReceived; 100 | 101 | process.Start(); 102 | process.BeginOutputReadLine(); 103 | process.BeginErrorReadLine(); 104 | process.WaitForExit(); 105 | 106 | txtOutput.AppendText("Exit code: " + process.ExitCode); 107 | 108 | if (process.ExitCode == EXIT_CODE_SUCCESS) 109 | { 110 | File.SetLastWriteTime(Path.Combine(txtTargetFolder.Text, txtFileName.Text), DateTime.Now); 111 | lblOutputStatus.Text = "CAB file successfully created."; 112 | lblOutputStatus.ForeColor = Color.Green; 113 | } 114 | else 115 | { 116 | lblOutputStatus.Text = "CAB file not created. See output for details."; 117 | lblOutputStatus.ForeColor = Color.Red; 118 | } 119 | } 120 | catch (Exception ex) 121 | { 122 | lblOutputStatus.Text = "CAB file not created. See output for details."; 123 | lblOutputStatus.ForeColor = Color.Red; 124 | 125 | txtOutput.AppendText("Error: " + ex.ToString()); 126 | txtOutput.ForeColor = Color.Red; 127 | } 128 | } 129 | 130 | btnRun.Enabled = true; 131 | } 132 | 133 | // capture output from console stdout to output box on form 134 | private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e) 135 | { 136 | this.BeginInvoke((MethodInvoker)delegate 137 | { 138 | if (e.Data != null) 139 | { 140 | txtOutput.AppendText(e.Data + Environment.NewLine); 141 | } 142 | }); 143 | } 144 | 145 | // capture output from console stderr to output box on form 146 | private void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e) 147 | { 148 | this.BeginInvoke((MethodInvoker)delegate 149 | { 150 | if (e.Data != null) 151 | { 152 | txtOutput.AppendText(e.Data + Environment.NewLine); 153 | txtOutput.ForeColor = Color.Red; 154 | } 155 | }); 156 | } 157 | 158 | private void MainForm_FormClosing(object sender, FormClosingEventArgs e) 159 | { 160 | if (chkRemember.Checked) 161 | { 162 | UserSettings.Save( 163 | txtSourceFolder.Text, 164 | chkRecursive.Checked, 165 | txtTargetFolder.Text, 166 | txtFileName.Text, 167 | EnumUtil.SafeParse(cboCompressType.SelectedItem as string, Constants.DefaultCompressionType), 168 | cboCompressMemory.SelectedItem as CompressionWindowSize); 169 | } 170 | else 171 | { 172 | UserSettings.Clear(); 173 | } 174 | } 175 | 176 | private void MainForm_Load(object sender, EventArgs e) 177 | { 178 | // Initialize drop-downs 179 | 180 | cboCompressType.Items.AddRange(Enum.GetNames(typeof(CompressionType))); 181 | cboCompressMemory.DataSource = Constants.CompressionWindowSizes; 182 | cboCompressMemory.DisplayMember = "Description"; 183 | cboCompressMemory.ValueMember = "Exponent"; 184 | 185 | // Set field values 186 | 187 | UserSettings settings = UserSettings.FetchWithDefaults(); 188 | 189 | txtSourceFolder.Text = settings.SourcePath; 190 | chkRecursive.Checked = settings.IncludeSubfolders; 191 | txtTargetFolder.Text = settings.TargetPath; 192 | txtFileName.Text = settings.FileName; 193 | 194 | cboCompressType.SelectedItem = Enum.GetName(typeof(CompressionType), settings.CompressionType); 195 | cboCompressMemory.SelectedValue = settings.CompressionWindowSize; 196 | 197 | lblVersion.Text = Assembly.GetExecutingAssembly().GetName().Version.ToString(2); 198 | } 199 | 200 | private void cboCompressType_SelectedIndexChanged(object sender, EventArgs e) 201 | { 202 | CompressionType compressionType = EnumUtil.SafeParse( 203 | cboCompressType.SelectedItem as string, Constants.DefaultCompressionType); 204 | 205 | cboCompressMemory.Enabled = DdfFileBuilder.IsCompressionWindowSizeIncluded(compressionType); 206 | } 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /MainForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | 123 | AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAAMMOAADDDgAAAAAAAAAA 124 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 125 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 126 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 127 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 128 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 129 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 130 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA37aYAOzR 131 | vADKiFgEw3pFBsN6RQbDekUGw3pFBsN6RQbDekUGw3pFBsN6RQbDekUGw3pFBsN6RQbDekUGx4JPBdWe 132 | dgDVnXUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMFz 133 | OgCtSgAAtVsYPrBRC6yuTgi3rk4Itq5OCLauTgi2rk4Itq5OCLauTgi2rk4Itq5OCLauTgi2rk4Itq5O 134 | CLavTwixslQPUQAAAADFfUcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 135 | AAAAAAAA0513APjv6wKxVA+ltlYG/851Fv/Pdxf/z3cX/893F//Pdxf/z3cX/893F//Pdxf/z3cX/893 136 | F//Pdxf/z3cX/7tcCf+vUAjEvnA1DL1vMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 137 | AAAAAAAAAAAAAAAAAADWo34A4buhBrJWE7bMcxX//7c4//+3OP//tjb//7Y1//+2Nf//tjX//7Y1//+2 138 | Nf//tjX//7Y2//+3OP//uDn/2IId/69OB828ay4QvGwvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 139 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAANajfgDhu6EGslYTts11Fv//tjj//7Y5///Ndv//2pv//9qa///a 140 | mv//2pr//9qa///am///0YL//7g9//+4Of/ZhB7/r08HzbxrLhC8bC8AAAAAAAAAAAAAAAAAAAAAAAAA 141 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1qN+AOG7oQayVhO2zXUW//+2OP//tzr//9ue///w 142 | 1f//79P//+/T///v0///79P///DV///jsf//ukL//7c4/9mEHv+vTwfNvGsuELxsLwAAAAAAAAAAAAAA 143 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWo34A4buhBrJWE7bNdRb//7Y4//+2 144 | OP//tzz//7pB//+7Qv//u0L//7tC//+7Qv//ukL//7g9//+2OP//uDn/2YQe/69PB828ay4QvGwvAAAA 145 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANajfgDhu6EGslYTts11 146 | Fv//tjj//7Y4//+2OP/3rDL/6Zgn/+iXJv/olyb/6Jcm//SoMP//tjj//7Y4//+4Of/ZhB7/r08Hzbxr 147 | LhC8bC8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1qN+AOG7 148 | oQayVhO2zXUW//+2OP//tjj//7c4/9yKJ//UnnT/37WV/961lP/Yp4L/1IMq//61N///tjj//7g5/9mE 149 | Hv+vTwfNvGsuELxsLwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 150 | AADWo34A4buhBrJWE7bNdRb//7Y4//+2OP//tzj/2Ygq/+zXyv////////////Xp4v/Uhzb//rQ1//+2 151 | OP//uDn/2YQe/69PB828ay4QvGwvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 152 | AAAAAAAAAAAAANajfgDhu6EGslYTts11Fv//tjj//7Y4//+3OP/gjyf/z41V/9ada//WnGv/0pNe/9iH 153 | KP//tTf//7Y4//+4Of/ZhB7/r08HzbxrLhC8bC8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 154 | AAAAAAAAAAAAAAAAAAAAAAAA1qN+AOG7oQayVhO2y3IU//61N//+tTf//rU3//uxNf/zpS3/8qQs//Kk 155 | LP/ypCz/+a80//61N//+tTf//7Y4/9eBHP+vTgfNvGsuELxsLwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 156 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWo34A4buhBrNYFLazUwT/xmsR/8dtEv/HbRL/x20S/8ht 157 | Ev/IbRL/yG0S/8htEv/HbRL/x20S/8dtEv/HbBL/t1cH/69PCM28ay4QvGwvAAAAAAAAAAAAAAAAAAAA 158 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANajfgDhu6EGs1gUtrVVBv/LcRT/zHMV/8xz 159 | Ff/McxX/zHMV/8xzFf/McxX/zHMV/8xzFf/McxX/zHMV/8xzFf+5Wgj/r08IzbxrLhC8bC8AAAAAAAAA 160 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1qN+AOG7oQayVhO2zHMV//+2 161 | OP//tjj//7U2//+1Nf//tTX//7U1//+1Nf//tTX//7U1//+1Nv//tjj//7c5/9eCHf+vTgfNvGsuELxs 162 | LwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWo34A4buhBrJW 163 | E7bNdRb//7Y4//+2Of//y3L//9iV///YlP//2JT//9iU///YlP//2JX//9B9//+4Pf//uDn/2YQe/69P 164 | B828ay4QvGwvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANaj 165 | fgDhu6EGslYTts11Fv//tjj//7c7///cof//8dn///DX///w1///8Nf///DX///x2f//5LT//7pC//+3 166 | OP/ZhB7/r08HzbxrLhC8bC8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 167 | AAAAAAAA1qN+AOG7oQayVhO2zXUW//+2OP//tjj//7g9//+7Q///vET//7xE//+8RP//vET//7tE//+5 168 | P///tjj//7g5/9mEHv+vTwfNvGsuELxsLwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 169 | AAAAAAAAAAAAAAAAAADWo34A4buhBrJWE7bNdRb//7Y4//+2OP//tjj/+K0y/+uaKP/qmSf/6pkn/+qZ 170 | J//1qTD//7Y4//+2OP//uDn/2YQe/69PB828ay4QvGwvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 171 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAANajfgDhu6EGslYTts11Fv//tjj//7Y4//+3OP/ciif/05tw/96x 172 | j//dsY7/16R9/9WEKv/+tTf//7Y4//+4Of/ZhB7/r08HzbxrLhC8bC8AAAAAAAAAAAAAAAAAAAAAAAAA 173 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1qN+AOG7oQayVhO2zXUW//+2OP//tjj//7c4/9mI 174 | Kv/s18r////////////16eL/1Ic2//60Nf//tjj//7g5/9mEHv+vTwfNvGsuELxsLwAAAAAAAAAAAAAA 175 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWo34A4buhBrJWE7bNdRb//7Y4//+2 176 | OP//tzj/344n/8+PWP/WoG//1qBv/9GVYv/Xhij//7U3//+2OP//uDn/2YQe/69PB828ay4QvGwvAAAA 177 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANajfgDhu6EGslYTtsty 178 | Ff//tjj//7Y4//+2OP/7sTX/8qQs//GjK//xoyv/8aMs//qvNP//tjj//7Y4//+3Of/XgR3/r04Hzbxr 179 | LhC8bC8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1KB5AP// 180 | /wKxUw6htVQF/8lvE//KcRT/ynEU/8pxFP/LchX/y3IV/8tyFf/LchX/y3EU/8pxFP/KcRT/ynEU/7hZ 181 | CP+vTwjBwHM6DL9yOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 182 | AAC9aSsAsFAJALNVEDOuTQWVq0cAnKtHAJyrRwCcq0cAnKtHAJyrRwCcq0cAnKtHAJyrRwCcq0cAnKtH 183 | AJyrRwCcrUoCmbBRCkSIAAAAx4FOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 184 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 185 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 186 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 187 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 188 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 189 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 190 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 191 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 192 | AAAAAAAAAAAAAAAAAAAAAAAA/////////////////4AB//8AAP/+AAB//gAAf/4AAH/+AAB//gAAf/4A 193 | AH/+AAB//gAAf/4AAH/+AAB//gAAf/4AAH/+AAB//gAAf/4AAH/+AAB//gAAf/4AAH/+AAB//gAAf/4A 194 | AH/+AAB//wAA//////////////////////8= 195 | 196 | 197 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace CabMaker 5 | { 6 | static class Program 7 | { 8 | /// 9 | /// The main entry point for the application. 10 | /// 11 | [STAThread] 12 | static void Main() 13 | { 14 | Application.EnableVisualStyles(); 15 | Application.SetCompatibleTextRenderingDefault(false); 16 | Application.Run(new MainForm()); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CabMaker")] 9 | [assembly: AssemblyDescription("Creates a Cabinet (CAB) file using the makecab.exe utility that's built into Microsoft Windows.")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("CabMaker")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5d270624-b71e-43ce-bd48-2c504da2a101")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.6.1.0")] 36 | [assembly: AssemblyFileVersion("1.6.1.0")] 37 | -------------------------------------------------------------------------------- /Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CabMaker.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CabMaker.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CabMaker.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.6.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CabMaker 2 | 3 | CabMaker is a free tool that lets you quickly and easily package up a folder of files into a .cab (Cabinet) file. 4 | 5 | It's essentially a GUI for makecab.exe (the command-line utility that ships with Windows). 6 | 7 | Screenshot of CabMaker GUI for makecab.exe 8 | 9 | It's a helpful utility for scenarios like SharePoint and InfoPath development. Both of those rely on .cab files but with different file extensions (.wsp for SharePoint and .xsn for InfoPath). 10 | 11 | CabMaker does _not_ support every single option that's built into makecab.exe, nor does it support the entire range of options provided by the [cab file spec](https://msdn.microsoft.com/en-us/library/bb417343.aspx). If you need additional options, please edit the source code and add whatever you need to suit your requirements. 12 | 13 | This was a tool I built in literally 5 minutes to help with SharePoint development as described [in this blog post](https://yieldreturnpost.wordpress.com/2016/06/22/free-tool-to-create-cab-file-from-folder/), so please keep that in mind when downloading and using the tool. 14 | 15 | Enjoy! 16 | -------------------------------------------------------------------------------- /StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace CabMaker 5 | { 6 | static class StringExtensions 7 | { 8 | /// 9 | /// Adds surrounding double quotes to a string if not already present. 10 | /// 11 | /// 12 | /// Input string surrounded by double quotes (or null if input string was null) 13 | /// 14 | public static string EnsureQuoted(this string input) 15 | { 16 | string result = input; 17 | 18 | if (input != null && !(input.StartsWith("\"") && input.EndsWith("\""))) 19 | { 20 | result = String.Format("\"{0}\"", input); 21 | } 22 | 23 | return result; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /UserSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO.IsolatedStorage; 3 | using System.Windows.Forms; 4 | 5 | namespace CabMaker 6 | { 7 | [Serializable] 8 | public class UserSettings 9 | { 10 | static readonly string _settingsFileName = $"{Application.ProductName}.dat"; 11 | 12 | public string SourcePath { get; set; } 13 | public bool IncludeSubfolders { get; set; } 14 | public string TargetPath { get; set; } 15 | public string FileName { get; set; } 16 | public CompressionType CompressionType { get; set; } 17 | public int CompressionWindowSize { get; set; } 18 | 19 | public UserSettings() 20 | { 21 | SourcePath = ""; 22 | IncludeSubfolders = true; 23 | TargetPath = ""; 24 | FileName = ""; 25 | CompressionType = Constants.DefaultCompressionType; 26 | CompressionWindowSize = Constants.DefaultCompressionWindowSize.Exponent; 27 | } 28 | 29 | public static void Clear() 30 | { 31 | // HACK: 32 | // For whatever reason, deleting files from isolated storage never seems to work (throws an exception every time). 33 | // So... as a workaround, we'll simply save the default settings to "clear out" user-saved settings. If anyone 34 | // out there has more time than me to investigate/fix this, please feel free. I'd love to find a better solution. 35 | 36 | var defaultSettings = new UserSettings(); 37 | 38 | Save(defaultSettings); 39 | } 40 | 41 | public static UserSettings FetchWithDefaults() 42 | { 43 | using (var storage = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, null, null)) 44 | { 45 | return storage.LoadObject(_settingsFileName) ?? new UserSettings(); 46 | } 47 | } 48 | 49 | public static void Save( 50 | string sourceFolder, 51 | bool isRecursive, 52 | string targetFolder, 53 | string targetFileName, 54 | CompressionType compressionType, 55 | CompressionWindowSize compressionWindowSize) 56 | { 57 | UserSettings settings = new UserSettings() 58 | { 59 | SourcePath = sourceFolder, 60 | IncludeSubfolders = isRecursive, 61 | TargetPath = targetFolder, 62 | FileName = targetFileName, 63 | CompressionType = compressionType, 64 | CompressionWindowSize = compressionWindowSize.Exponent 65 | }; 66 | 67 | Save(settings); 68 | } 69 | 70 | public static void Save(UserSettings settings) 71 | { 72 | using (var storage = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, null, null)) 73 | { 74 | storage.SaveObject(settings, _settingsFileName); 75 | } 76 | } 77 | } 78 | } 79 | --------------------------------------------------------------------------------