diff options
Diffstat (limited to '')
-rw-r--r-- | src/WixToolset.Core.Native/Cabinet.cs | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/src/WixToolset.Core.Native/Cabinet.cs b/src/WixToolset.Core.Native/Cabinet.cs new file mode 100644 index 00000000..27b0ec74 --- /dev/null +++ b/src/WixToolset.Core.Native/Cabinet.cs | |||
@@ -0,0 +1,199 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Core.Native | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections.Generic; | ||
7 | using System.Linq; | ||
8 | |||
9 | /// <summary> | ||
10 | /// Wrapper class around interop with wixcab.dll to compress files into a cabinet. | ||
11 | /// </summary> | ||
12 | public sealed class Cabinet | ||
13 | { | ||
14 | private const string CompressionLevelVariable = "WIX_COMPRESSION_LEVEL"; | ||
15 | private static readonly char[] TextLineSplitter = new[] { '\t' }; | ||
16 | |||
17 | public Cabinet(string path) | ||
18 | { | ||
19 | this.Path = path; | ||
20 | } | ||
21 | |||
22 | public string Path { get; } | ||
23 | |||
24 | /// <summary> | ||
25 | /// Creates a cabinet. | ||
26 | /// </summary> | ||
27 | /// <param name="cabPath">Path of cabinet to create.</param> | ||
28 | /// <param name="compressionLevel">Level of compression to apply.</param> | ||
29 | /// <param name="maxFiles">Maximum number of files that will be added to cabinet.</param> | ||
30 | /// <param name="maxSize">Maximum size of cabinet.</param> | ||
31 | /// <param name="maxThresh">Maximum threshold for each cabinet.</param> | ||
32 | public void Compress(IEnumerable<CabinetCompressFile> files, CabinetCompressionLevel compressionLevel, int maxSize = 0, int maxThresh = 0) | ||
33 | { | ||
34 | var compressionLevelVariable = Environment.GetEnvironmentVariable(CompressionLevelVariable); | ||
35 | |||
36 | // Override authored compression level if environment variable is present. | ||
37 | if (!String.IsNullOrEmpty(compressionLevelVariable)) | ||
38 | { | ||
39 | if (!Enum.TryParse(compressionLevelVariable, true, out compressionLevel)) | ||
40 | { | ||
41 | //throw new WixException(WixErrors.IllegalEnvironmentVariable(CompressionLevelVariable, compressionLevelVariable)); | ||
42 | throw new ArgumentException(); | ||
43 | } | ||
44 | } | ||
45 | |||
46 | var wixnative = new WixNativeExe("smartcab", this.Path, Convert.ToInt32(compressionLevel), files.Count(), maxSize, maxThresh); | ||
47 | |||
48 | foreach (var file in files) | ||
49 | { | ||
50 | wixnative.AddStdinLine(file.ToWixNativeStdinLine()); | ||
51 | } | ||
52 | |||
53 | wixnative.Run(); | ||
54 | |||
55 | #if TOOD_ERROR_HANDLING | ||
56 | catch (COMException ce) | ||
57 | { | ||
58 | // If we get a "the file exists" error, we must have a full temp directory - so report the issue | ||
59 | if (0x80070050 == unchecked((uint)ce.ErrorCode)) | ||
60 | { | ||
61 | throw new WixException(WixErrors.FullTempDirectory("WSC", Path.GetTempPath())); | ||
62 | } | ||
63 | |||
64 | throw; | ||
65 | } | ||
66 | #endif | ||
67 | } | ||
68 | |||
69 | /// <summary> | ||
70 | /// Enumerates all files in a cabinet. | ||
71 | /// </summary> | ||
72 | /// <returns>>List of CabinetFileInfo</returns> | ||
73 | public List<CabinetFileInfo> Enumerate() | ||
74 | { | ||
75 | var wixnative = new WixNativeExe("enumcab", this.Path); | ||
76 | var lines = wixnative.Run(); | ||
77 | |||
78 | var fileInfoList = new List<CabinetFileInfo>(); | ||
79 | |||
80 | foreach (var line in lines) | ||
81 | { | ||
82 | if (String.IsNullOrEmpty(line)) | ||
83 | { | ||
84 | continue; | ||
85 | } | ||
86 | |||
87 | var data = line.Split(TextLineSplitter, StringSplitOptions.None); | ||
88 | |||
89 | var size = Convert.ToInt32(data[1]); | ||
90 | var date = Convert.ToInt32(data[2]); | ||
91 | var time = Convert.ToInt32(data[3]); | ||
92 | |||
93 | fileInfoList.Add(new CabinetFileInfo(data[0], size, date, time)); | ||
94 | } | ||
95 | |||
96 | return fileInfoList; | ||
97 | } | ||
98 | |||
99 | /// <summary> | ||
100 | /// Extracts all the files from a cabinet to a directory. | ||
101 | /// </summary> | ||
102 | /// <param name="outputFolder">Directory to extract files to.</param> | ||
103 | public void Extract(string outputFolder) | ||
104 | { | ||
105 | if (!outputFolder.EndsWith("\\", StringComparison.Ordinal)) | ||
106 | { | ||
107 | outputFolder += "\\"; | ||
108 | } | ||
109 | |||
110 | var wixnative = new WixNativeExe("extractcab", this.Path, outputFolder); | ||
111 | wixnative.Run(); | ||
112 | } | ||
113 | |||
114 | #if TOOD_ERROR_HANDLING | ||
115 | /// <summary> | ||
116 | /// Adds a file to the cabinet with an optional MSI file hash. | ||
117 | /// </summary> | ||
118 | /// <param name="file">The file to add.</param> | ||
119 | /// <param name="token">The token for the file.</param> | ||
120 | /// <param name="fileHash">The MSI file hash of the file.</param> | ||
121 | //private void AddFile(string file, string token, MsiInterop.MSIFILEHASHINFO fileHash) | ||
122 | //{ | ||
123 | // try | ||
124 | // { | ||
125 | // NativeMethods.CreateCabAddFile(file, token, fileHash, this.handle); | ||
126 | // } | ||
127 | // catch (COMException ce) | ||
128 | // { | ||
129 | // if (0x80004005 == unchecked((uint)ce.ErrorCode)) // E_FAIL | ||
130 | // { | ||
131 | // throw new WixException(WixErrors.CreateCabAddFileFailed()); | ||
132 | // } | ||
133 | // else if (0x80070070 == unchecked((uint)ce.ErrorCode)) // ERROR_DISK_FULL | ||
134 | // { | ||
135 | // throw new WixException(WixErrors.CreateCabInsufficientDiskSpace()); | ||
136 | // } | ||
137 | // else | ||
138 | // { | ||
139 | // throw; | ||
140 | // } | ||
141 | // } | ||
142 | // catch (DirectoryNotFoundException) | ||
143 | // { | ||
144 | // throw new WixFileNotFoundException(file); | ||
145 | // } | ||
146 | // catch (FileNotFoundException) | ||
147 | // { | ||
148 | // throw new WixFileNotFoundException(file); | ||
149 | // } | ||
150 | //} | ||
151 | |||
152 | /// <summary> | ||
153 | /// Complete/commit the cabinet - this must be called before Dispose so that errors will be | ||
154 | /// reported on the same thread. | ||
155 | /// </summary> | ||
156 | /// <param name="newCabNamesCallBackAddress">Address of Binder's callback function for Cabinet Splitting</param> | ||
157 | public void Complete(IntPtr newCabNamesCallBackAddress) | ||
158 | { | ||
159 | if (IntPtr.Zero != this.handle) | ||
160 | { | ||
161 | try | ||
162 | { | ||
163 | if (newCabNamesCallBackAddress != IntPtr.Zero && this.maxSize != 0) | ||
164 | { | ||
165 | NativeMethods.CreateCabFinish(this.handle, newCabNamesCallBackAddress); | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | NativeMethods.CreateCabFinish(this.handle, IntPtr.Zero); | ||
170 | } | ||
171 | |||
172 | GC.SuppressFinalize(this); | ||
173 | this.disposed = true; | ||
174 | } | ||
175 | catch (COMException ce) | ||
176 | { | ||
177 | //if (0x80004005 == unchecked((uint)ce.ErrorCode)) // E_FAIL | ||
178 | //{ | ||
179 | // // This error seems to happen, among other situations, when cabbing more than 0xFFFF files | ||
180 | // throw new WixException(WixErrors.FinishCabFailed()); | ||
181 | //} | ||
182 | //else if (0x80070070 == unchecked((uint)ce.ErrorCode)) // ERROR_DISK_FULL | ||
183 | //{ | ||
184 | // throw new WixException(WixErrors.CreateCabInsufficientDiskSpace()); | ||
185 | //} | ||
186 | //else | ||
187 | //{ | ||
188 | // throw; | ||
189 | //} | ||
190 | } | ||
191 | finally | ||
192 | { | ||
193 | this.handle = IntPtr.Zero; | ||
194 | } | ||
195 | } | ||
196 | } | ||
197 | #endif | ||
198 | } | ||
199 | } | ||