diff options
Diffstat (limited to 'src/wix/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs')
-rw-r--r-- | src/wix/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs | 455 |
1 files changed, 455 insertions, 0 deletions
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs new file mode 100644 index 00000000..83a4949e --- /dev/null +++ b/src/wix/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs | |||
@@ -0,0 +1,455 @@ | |||
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.WindowsInstaller.Bind | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections.Generic; | ||
7 | using System.Globalization; | ||
8 | using System.IO; | ||
9 | using System.Linq; | ||
10 | using System.Runtime.InteropServices; | ||
11 | using WixToolset.Data; | ||
12 | using WixToolset.Data.Symbols; | ||
13 | using WixToolset.Data.WindowsInstaller; | ||
14 | using WixToolset.Extensibility; | ||
15 | using WixToolset.Extensibility.Data; | ||
16 | using WixToolset.Extensibility.Services; | ||
17 | |||
18 | /// <summary> | ||
19 | /// Creates cabinet files. | ||
20 | /// </summary> | ||
21 | internal class CreateCabinetsCommand | ||
22 | { | ||
23 | public const int DefaultMaximumUncompressedMediaSize = 200; // Default value is 200 MB | ||
24 | public const int MaxValueOfMaxCabSizeForLargeFileSplitting = 2 * 1024; // 2048 MB (i.e. 2 GB) | ||
25 | |||
26 | private readonly List<IFileTransfer> fileTransfers; | ||
27 | |||
28 | private readonly List<ITrackedFile> trackedFiles; | ||
29 | |||
30 | private readonly FileSplitCabNamesCallback newCabNamesCallBack; | ||
31 | |||
32 | private Dictionary<string, string> lastCabinetAddedToMediaTable; // Key is First Cabinet Name, Value is Last Cabinet Added in the Split Sequence | ||
33 | |||
34 | public CreateCabinetsCommand(IServiceProvider serviceProvider, IBackendHelper backendHelper, WixMediaTemplateSymbol mediaTemplate) | ||
35 | { | ||
36 | this.fileTransfers = new List<IFileTransfer>(); | ||
37 | |||
38 | this.trackedFiles = new List<ITrackedFile>(); | ||
39 | |||
40 | this.newCabNamesCallBack = this.NewCabNamesCallBack; | ||
41 | |||
42 | this.ServiceProvider = serviceProvider; | ||
43 | |||
44 | this.BackendHelper = backendHelper; | ||
45 | |||
46 | this.MediaTemplate = mediaTemplate; | ||
47 | } | ||
48 | |||
49 | private IServiceProvider ServiceProvider { get; } | ||
50 | |||
51 | private IBackendHelper BackendHelper { get; } | ||
52 | |||
53 | private WixMediaTemplateSymbol MediaTemplate { get; } | ||
54 | |||
55 | /// <summary> | ||
56 | /// Sets the number of threads to use for cabinet creation. | ||
57 | /// </summary> | ||
58 | public int CabbingThreadCount { private get; set; } | ||
59 | |||
60 | public string CabCachePath { private get; set; } | ||
61 | |||
62 | public IMessaging Messaging { private get; set; } | ||
63 | |||
64 | public string IntermediateFolder { private get; set; } | ||
65 | |||
66 | /// <summary> | ||
67 | /// Sets the default compression level to use for cabinets | ||
68 | /// that don't have their compression level explicitly set. | ||
69 | /// </summary> | ||
70 | public CompressionLevel? DefaultCompressionLevel { private get; set; } | ||
71 | |||
72 | public IEnumerable<IWindowsInstallerBackendBinderExtension> BackendExtensions { private get; set; } | ||
73 | |||
74 | public WindowsInstallerData Data { private get; set; } | ||
75 | |||
76 | public string LayoutDirectory { private get; set; } | ||
77 | |||
78 | public bool Compressed { private get; set; } | ||
79 | |||
80 | public string ModularizationSuffix { private get; set; } | ||
81 | |||
82 | public Dictionary<MediaSymbol, IEnumerable<IFileFacade>> FileFacadesByCabinet { private get; set; } | ||
83 | |||
84 | public Func<MediaSymbol, string, string, string> ResolveMedia { private get; set; } | ||
85 | |||
86 | public TableDefinitionCollection TableDefinitions { private get; set; } | ||
87 | |||
88 | public IEnumerable<IFileTransfer> FileTransfers => this.fileTransfers; | ||
89 | |||
90 | public IEnumerable<ITrackedFile> TrackedFiles => this.trackedFiles; | ||
91 | |||
92 | public void Execute() | ||
93 | { | ||
94 | this.lastCabinetAddedToMediaTable = new Dictionary<string, string>(); | ||
95 | |||
96 | // If the cabbing thread count wasn't provided, default the number of cabbing threads to the number of processors. | ||
97 | if (this.CabbingThreadCount <= 0) | ||
98 | { | ||
99 | this.CabbingThreadCount = this.CalculateCabbingThreadCount(); | ||
100 | |||
101 | this.Messaging.Write(VerboseMessages.SetCabbingThreadCount(this.CabbingThreadCount.ToString())); | ||
102 | } | ||
103 | |||
104 | // Send Binder object to Facilitate NewCabNamesCallBack Callback | ||
105 | var cabinetBuilder = new CabinetBuilder(this.Messaging, this.CabbingThreadCount, Marshal.GetFunctionPointerForDelegate(this.newCabNamesCallBack)); | ||
106 | |||
107 | // Supply Compile MediaTemplate Attributes to Cabinet Builder | ||
108 | this.GetMediaTemplateAttributes(out var maximumCabinetSizeForLargeFileSplitting, out var maximumUncompressedMediaSize); | ||
109 | cabinetBuilder.MaximumCabinetSizeForLargeFileSplitting = maximumCabinetSizeForLargeFileSplitting; | ||
110 | cabinetBuilder.MaximumUncompressedMediaSize = maximumUncompressedMediaSize; | ||
111 | |||
112 | foreach (var entry in this.FileFacadesByCabinet) | ||
113 | { | ||
114 | var mediaSymbol = entry.Key; | ||
115 | var files = entry.Value; | ||
116 | var compressionLevel = mediaSymbol.CompressionLevel ?? this.DefaultCompressionLevel ?? CompressionLevel.Medium; | ||
117 | var cabinetDir = this.ResolveMedia(mediaSymbol, mediaSymbol.Layout, this.LayoutDirectory); | ||
118 | |||
119 | var cabinetWorkItem = this.CreateCabinetWorkItem(this.Data, cabinetDir, mediaSymbol, compressionLevel, files); | ||
120 | if (null != cabinetWorkItem) | ||
121 | { | ||
122 | cabinetBuilder.Enqueue(cabinetWorkItem); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | // stop processing if an error previously occurred | ||
127 | if (this.Messaging.EncounteredError) | ||
128 | { | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | // create queued cabinets with multiple threads | ||
133 | cabinetBuilder.CreateQueuedCabinets(); | ||
134 | if (this.Messaging.EncounteredError) | ||
135 | { | ||
136 | return; | ||
137 | } | ||
138 | } | ||
139 | |||
140 | private int CalculateCabbingThreadCount() | ||
141 | { | ||
142 | var cabbingThreadCount = Environment.ProcessorCount; | ||
143 | |||
144 | if (cabbingThreadCount <= 0) | ||
145 | { | ||
146 | cabbingThreadCount = 1; // reset to 1 when the environment variable is invalid. | ||
147 | |||
148 | this.Messaging.Write(WarningMessages.InvalidEnvironmentVariable("NUMBER_OF_PROCESSORS", Environment.ProcessorCount.ToString(), cabbingThreadCount.ToString())); | ||
149 | } | ||
150 | |||
151 | return cabbingThreadCount; | ||
152 | } | ||
153 | |||
154 | /// <summary> | ||
155 | /// Creates a work item to create a cabinet. | ||
156 | /// </summary> | ||
157 | /// <param name="data">Windows Installer data for the current database.</param> | ||
158 | /// <param name="cabinetDir">Directory to create cabinet in.</param> | ||
159 | /// <param name="mediaSymbol">Media symbol containing information about the cabinet.</param> | ||
160 | /// <param name="compressionLevel">Desired compression level.</param> | ||
161 | /// <param name="fileFacades">Collection of files in this cabinet.</param> | ||
162 | /// <returns>created CabinetWorkItem object</returns> | ||
163 | private CabinetWorkItem CreateCabinetWorkItem(WindowsInstallerData data, string cabinetDir, MediaSymbol mediaSymbol, CompressionLevel compressionLevel, IEnumerable<IFileFacade> fileFacades) | ||
164 | { | ||
165 | CabinetWorkItem cabinetWorkItem = null; | ||
166 | var tempCabinetFileX = Path.Combine(this.IntermediateFolder, mediaSymbol.Cabinet); | ||
167 | |||
168 | // check for an empty cabinet | ||
169 | if (!fileFacades.Any()) | ||
170 | { | ||
171 | // Remove the leading '#' from the embedded cabinet name to make the warning easier to understand | ||
172 | var cabinetName = mediaSymbol.Cabinet.TrimStart('#'); | ||
173 | |||
174 | // If building a patch, remind them to run -p for torch. | ||
175 | if (OutputType.Patch == data.Type) | ||
176 | { | ||
177 | this.Messaging.Write(WarningMessages.EmptyCabinet(mediaSymbol.SourceLineNumbers, cabinetName, true)); | ||
178 | } | ||
179 | else | ||
180 | { | ||
181 | this.Messaging.Write(WarningMessages.EmptyCabinet(mediaSymbol.SourceLineNumbers, cabinetName)); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | var cabinetResolver = new CabinetResolver(this.ServiceProvider, this.CabCachePath, this.BackendExtensions); | ||
186 | |||
187 | var resolvedCabinet = cabinetResolver.ResolveCabinet(tempCabinetFileX, fileFacades); | ||
188 | |||
189 | // create a cabinet work item if it's not being skipped | ||
190 | if (CabinetBuildOption.BuildAndCopy == resolvedCabinet.BuildOption || CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption) | ||
191 | { | ||
192 | // Default to the threshold for best smartcabbing (makes smallest cabinet). | ||
193 | cabinetWorkItem = new CabinetWorkItem(fileFacades, resolvedCabinet.Path, maxThreshold: 0, compressionLevel, this.ModularizationSuffix /*, this.FileManager*/); | ||
194 | } | ||
195 | else // reuse the cabinet from the cabinet cache. | ||
196 | { | ||
197 | this.Messaging.Write(VerboseMessages.ReusingCabCache(mediaSymbol.SourceLineNumbers, mediaSymbol.Cabinet, resolvedCabinet.Path)); | ||
198 | |||
199 | try | ||
200 | { | ||
201 | // Ensure the cached cabinet timestamp is current to prevent perpetual incremental builds. The | ||
202 | // problematic scenario goes like this. Imagine two cabinets in the cache. Update a file that | ||
203 | // goes into one of the cabinets. One cabinet will get rebuilt, the other will be copied from | ||
204 | // the cache. Now the file (an input) has a newer timestamp than the reused cabient (an output) | ||
205 | // causing the project to look like it perpetually needs a rebuild until all of the reused | ||
206 | // cabinets get newer timestamps. | ||
207 | File.SetLastWriteTime(resolvedCabinet.Path, DateTime.Now); | ||
208 | } | ||
209 | catch (Exception e) | ||
210 | { | ||
211 | this.Messaging.Write(WarningMessages.CannotUpdateCabCache(mediaSymbol.SourceLineNumbers, resolvedCabinet.Path, e.Message)); | ||
212 | } | ||
213 | } | ||
214 | |||
215 | var trackResolvedCabinet = this.BackendHelper.TrackFile(resolvedCabinet.Path, TrackedFileType.Intermediate, mediaSymbol.SourceLineNumbers); | ||
216 | this.trackedFiles.Add(trackResolvedCabinet); | ||
217 | |||
218 | if (mediaSymbol.Cabinet.StartsWith("#", StringComparison.Ordinal)) | ||
219 | { | ||
220 | var streamsTable = data.EnsureTable(this.TableDefinitions["_Streams"]); | ||
221 | |||
222 | var streamRow = streamsTable.CreateRow(mediaSymbol.SourceLineNumbers); | ||
223 | streamRow[0] = mediaSymbol.Cabinet.Substring(1); | ||
224 | streamRow[1] = resolvedCabinet.Path; | ||
225 | } | ||
226 | else | ||
227 | { | ||
228 | var trackDestination = this.BackendHelper.TrackFile(Path.Combine(cabinetDir, mediaSymbol.Cabinet), TrackedFileType.Final, mediaSymbol.SourceLineNumbers); | ||
229 | this.trackedFiles.Add(trackDestination); | ||
230 | |||
231 | var transfer = this.BackendHelper.CreateFileTransfer(resolvedCabinet.Path, trackDestination.Path, resolvedCabinet.BuildOption == CabinetBuildOption.BuildAndMove, mediaSymbol.SourceLineNumbers); | ||
232 | this.fileTransfers.Add(transfer); | ||
233 | } | ||
234 | |||
235 | return cabinetWorkItem; | ||
236 | } | ||
237 | |||
238 | //private ResolvedCabinet ResolveCabinet(string cabinetPath, IEnumerable<FileFacade> fileFacades) | ||
239 | //{ | ||
240 | // ResolvedCabinet resolved = null; | ||
241 | |||
242 | // List<BindFileWithPath> filesWithPath = fileFacades.Select(f => new BindFileWithPath() { Id = f.File.File, Path = f.WixFile.Source }).ToList(); | ||
243 | |||
244 | // foreach (var extension in this.BackendExtensions) | ||
245 | // { | ||
246 | // resolved = extension.ResolveCabinet(cabinetPath, filesWithPath); | ||
247 | // if (null != resolved) | ||
248 | // { | ||
249 | // break; | ||
250 | // } | ||
251 | // } | ||
252 | |||
253 | // return resolved; | ||
254 | //} | ||
255 | |||
256 | /// <summary> | ||
257 | /// Delegate for Cabinet Split Callback | ||
258 | /// </summary> | ||
259 | [UnmanagedFunctionPointer(CallingConvention.StdCall)] | ||
260 | internal delegate void FileSplitCabNamesCallback([MarshalAs(UnmanagedType.LPWStr)]string firstCabName, [MarshalAs(UnmanagedType.LPWStr)]string newCabName, [MarshalAs(UnmanagedType.LPWStr)]string fileToken); | ||
261 | |||
262 | /// <summary> | ||
263 | /// Call back to Add File Transfer for new Cab and add new Cab to Media table | ||
264 | /// This callback can come from Multiple Cabinet Builder Threads and so should be thread safe | ||
265 | /// This callback will not be called in case there is no File splitting. i.e. MaximumCabinetSizeForLargeFileSplitting was not authored | ||
266 | /// </summary> | ||
267 | /// <param name="firstCabName">The name of splitting cabinet without extention e.g. "cab1".</param> | ||
268 | /// <param name="newCabinetName">The name of the new cabinet that would be formed by splitting e.g. "cab1b.cab"</param> | ||
269 | /// <param name="fileToken">The file token of the first file present in the splitting cabinet</param> | ||
270 | internal void NewCabNamesCallBack([MarshalAs(UnmanagedType.LPWStr)]string firstCabName, [MarshalAs(UnmanagedType.LPWStr)]string newCabinetName, [MarshalAs(UnmanagedType.LPWStr)]string fileToken) | ||
271 | { | ||
272 | throw new NotImplementedException(); | ||
273 | #if TODO_CAB_SPANNING | ||
274 | // Locking Mutex here as this callback can come from Multiple Cabinet Builder Threads | ||
275 | var mutex = new Mutex(false, "WixCabinetSplitBinderCallback"); | ||
276 | try | ||
277 | { | ||
278 | if (!mutex.WaitOne(0, false)) // Check if you can get the lock | ||
279 | { | ||
280 | // Cound not get the Lock | ||
281 | this.Messaging.Write(VerboseMessages.CabinetsSplitInParallel()); | ||
282 | mutex.WaitOne(); // Wait on other thread | ||
283 | } | ||
284 | |||
285 | var firstCabinetName = firstCabName + ".cab"; | ||
286 | var transferAdded = false; // Used for Error Handling | ||
287 | |||
288 | // Create File Transfer for new Cabinet using transfer of Base Cabinet | ||
289 | foreach (var transfer in this.FileTransfers) | ||
290 | { | ||
291 | if (firstCabinetName.Equals(Path.GetFileName(transfer.Source), StringComparison.InvariantCultureIgnoreCase)) | ||
292 | { | ||
293 | var newCabSourcePath = Path.Combine(Path.GetDirectoryName(transfer.Source), newCabinetName); | ||
294 | var newCabTargetPath = Path.Combine(Path.GetDirectoryName(transfer.Destination), newCabinetName); | ||
295 | |||
296 | var trackSource = this.BackendHelper.TrackFile(newCabSourcePath, TrackedFileType.Intermediate, transfer.SourceLineNumbers); | ||
297 | this.trackedFiles.Add(trackSource); | ||
298 | |||
299 | var trackTarget = this.BackendHelper.TrackFile(newCabTargetPath, TrackedFileType.Final, transfer.SourceLineNumbers); | ||
300 | this.trackedFiles.Add(trackTarget); | ||
301 | |||
302 | var newTransfer = this.BackendHelper.CreateFileTransfer(trackSource.Path, trackTarget.Path, transfer.Move, transfer.SourceLineNumbers); | ||
303 | this.fileTransfers.Add(newTransfer); | ||
304 | |||
305 | transferAdded = true; | ||
306 | break; | ||
307 | } | ||
308 | } | ||
309 | |||
310 | // Check if File Transfer was added | ||
311 | if (!transferAdded) | ||
312 | { | ||
313 | throw new WixException(ErrorMessages.SplitCabinetCopyRegistrationFailed(newCabinetName, firstCabinetName)); | ||
314 | } | ||
315 | |||
316 | // Add the new Cabinets to media table using LastSequence of Base Cabinet | ||
317 | var mediaTable = this.Output.Tables["Media"]; | ||
318 | var wixFileTable = this.Output.Tables["WixFile"]; | ||
319 | var diskIDForLastSplitCabAdded = 0; // The DiskID value for the first cab in this cabinet split chain | ||
320 | var lastSequenceForLastSplitCabAdded = 0; // The LastSequence value for the first cab in this cabinet split chain | ||
321 | var lastSplitCabinetFound = false; // Used for Error Handling | ||
322 | |||
323 | var lastCabinetOfThisSequence = String.Empty; | ||
324 | // Get the Value of Last Cabinet Added in this split Sequence from Dictionary | ||
325 | if (!this.lastCabinetAddedToMediaTable.TryGetValue(firstCabinetName, out lastCabinetOfThisSequence)) | ||
326 | { | ||
327 | // If there is no value for this sequence, then use first Cabinet is the last one of this split sequence | ||
328 | lastCabinetOfThisSequence = firstCabinetName; | ||
329 | } | ||
330 | |||
331 | foreach (MediaRow mediaRow in mediaTable.Rows) | ||
332 | { | ||
333 | // Get details for the Last Cabinet Added in this Split Sequence | ||
334 | if ((lastSequenceForLastSplitCabAdded == 0) && lastCabinetOfThisSequence.Equals(mediaRow.Cabinet, StringComparison.InvariantCultureIgnoreCase)) | ||
335 | { | ||
336 | lastSequenceForLastSplitCabAdded = mediaRow.LastSequence; | ||
337 | diskIDForLastSplitCabAdded = mediaRow.DiskId; | ||
338 | lastSplitCabinetFound = true; | ||
339 | } | ||
340 | |||
341 | // Check for Name Collision for the new Cabinet added | ||
342 | if (newCabinetName.Equals(mediaRow.Cabinet, StringComparison.InvariantCultureIgnoreCase)) | ||
343 | { | ||
344 | // Name Collision of generated Split Cabinet Name and user Specified Cab name for current row | ||
345 | throw new WixException(ErrorMessages.SplitCabinetNameCollision(newCabinetName, firstCabinetName)); | ||
346 | } | ||
347 | } | ||
348 | |||
349 | // Check if the last Split Cabinet was found in the Media Table | ||
350 | if (!lastSplitCabinetFound) | ||
351 | { | ||
352 | throw new WixException(ErrorMessages.SplitCabinetInsertionFailed(newCabinetName, firstCabinetName, lastCabinetOfThisSequence)); | ||
353 | } | ||
354 | |||
355 | // The new Row has to be inserted just after the last cab in this cabinet split chain according to DiskID Sort | ||
356 | // This is because the FDI Extract requires DiskID of Split Cabinets to be continuous. It Fails otherwise with | ||
357 | // Error 2350 (FDI Server Error) as next DiskID did not have the right split cabinet during extraction | ||
358 | MediaRow newMediaRow = (MediaRow)mediaTable.CreateRow(null); | ||
359 | newMediaRow.Cabinet = newCabinetName; | ||
360 | newMediaRow.DiskId = diskIDForLastSplitCabAdded + 1; // When Sorted with DiskID, this new Cabinet Row is an Insertion | ||
361 | newMediaRow.LastSequence = lastSequenceForLastSplitCabAdded; | ||
362 | |||
363 | // Now increment the DiskID for all rows that come after the newly inserted row to Ensure that DiskId is unique | ||
364 | foreach (MediaRow mediaRow in mediaTable.Rows) | ||
365 | { | ||
366 | // Check if this row comes after inserted row and it is not the new cabinet inserted row | ||
367 | if (mediaRow.DiskId >= newMediaRow.DiskId && !newCabinetName.Equals(mediaRow.Cabinet, StringComparison.InvariantCultureIgnoreCase)) | ||
368 | { | ||
369 | mediaRow.DiskId++; // Increment DiskID | ||
370 | } | ||
371 | } | ||
372 | |||
373 | // Now Increment DiskID for All files Rows so that they refer to the right Media Row | ||
374 | foreach (WixFileRow wixFileRow in wixFileTable.Rows) | ||
375 | { | ||
376 | // Check if this row comes after inserted row and if this row is not the file that has to go into the current cabinet | ||
377 | // This check will work as we have only one large file in every splitting cabinet | ||
378 | // If we want to support splitting cabinet with more large files we need to update this code | ||
379 | if (wixFileRow.DiskId >= newMediaRow.DiskId && !wixFileRow.File.Equals(fileToken, StringComparison.InvariantCultureIgnoreCase)) | ||
380 | { | ||
381 | wixFileRow.DiskId++; // Increment DiskID | ||
382 | } | ||
383 | } | ||
384 | |||
385 | // Update the Last Cabinet Added in the Split Sequence in Dictionary for future callback | ||
386 | this.lastCabinetAddedToMediaTable[firstCabinetName] = newCabinetName; | ||
387 | |||
388 | mediaTable.ValidateRows(); // Valdiates DiskDIs, throws Exception as Wix Error if validation fails | ||
389 | } | ||
390 | finally | ||
391 | { | ||
392 | // Releasing the Mutex here | ||
393 | mutex.ReleaseMutex(); | ||
394 | } | ||
395 | #endif | ||
396 | } | ||
397 | |||
398 | |||
399 | /// <summary> | ||
400 | /// Gets Compiler Values of MediaTemplate Attributes governing Maximum Cabinet Size after applying Environment Variable Overrides | ||
401 | /// </summary> | ||
402 | private void GetMediaTemplateAttributes(out int maxCabSizeForLargeFileSplitting, out int maxUncompressedMediaSize) | ||
403 | { | ||
404 | // Get Environment Variable Overrides for MediaTemplate Attributes governing Maximum Cabinet Size | ||
405 | var mcslfsString = Environment.GetEnvironmentVariable("WIX_MCSLFS"); | ||
406 | var mumsString = Environment.GetEnvironmentVariable("WIX_MUMS"); | ||
407 | |||
408 | // Supply Compile MediaTemplate Attributes to Cabinet Builder | ||
409 | if (this.MediaTemplate != null) | ||
410 | { | ||
411 | // Get the Value for Max Cab Size for File Splitting | ||
412 | var maxCabSizeForLargeFileInMB = 0; | ||
413 | try | ||
414 | { | ||
415 | // Override authored mcslfs value if environment variable is authored. | ||
416 | maxCabSizeForLargeFileInMB = !String.IsNullOrEmpty(mcslfsString) ? Int32.Parse(mcslfsString) : this.MediaTemplate.MaximumCabinetSizeForLargeFileSplitting ?? MaxValueOfMaxCabSizeForLargeFileSplitting; | ||
417 | |||
418 | var testOverFlow = (ulong)maxCabSizeForLargeFileInMB * 1024 * 1024; | ||
419 | maxCabSizeForLargeFileSplitting = maxCabSizeForLargeFileInMB; | ||
420 | } | ||
421 | catch (FormatException) | ||
422 | { | ||
423 | throw new WixException(ErrorMessages.IllegalEnvironmentVariable("WIX_MCSLFS", mcslfsString)); | ||
424 | } | ||
425 | catch (OverflowException) | ||
426 | { | ||
427 | throw new WixException(ErrorMessages.MaximumCabinetSizeForLargeFileSplittingTooLarge(null, maxCabSizeForLargeFileInMB, MaxValueOfMaxCabSizeForLargeFileSplitting)); | ||
428 | } | ||
429 | |||
430 | var maxPreCompressedSizeInMB = 0; | ||
431 | try | ||
432 | { | ||
433 | // Override authored mums value if environment variable is authored. | ||
434 | maxPreCompressedSizeInMB = !String.IsNullOrEmpty(mumsString) ? Int32.Parse(mumsString) : this.MediaTemplate.MaximumUncompressedMediaSize ?? DefaultMaximumUncompressedMediaSize; | ||
435 | |||
436 | var testOverFlow = (ulong)maxPreCompressedSizeInMB * 1024 * 1024; | ||
437 | maxUncompressedMediaSize = maxPreCompressedSizeInMB; | ||
438 | } | ||
439 | catch (FormatException) | ||
440 | { | ||
441 | throw new WixException(ErrorMessages.IllegalEnvironmentVariable("WIX_MUMS", mumsString)); | ||
442 | } | ||
443 | catch (OverflowException) | ||
444 | { | ||
445 | throw new WixException(ErrorMessages.MaximumUncompressedMediaSizeTooLarge(null, maxPreCompressedSizeInMB)); | ||
446 | } | ||
447 | } | ||
448 | else | ||
449 | { | ||
450 | maxCabSizeForLargeFileSplitting = 0; | ||
451 | maxUncompressedMediaSize = DefaultMaximumUncompressedMediaSize; | ||
452 | } | ||
453 | } | ||
454 | } | ||
455 | } | ||