aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core.WindowsInstaller
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core.WindowsInstaller')
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs52
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs2
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CabinetResolver.cs14
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs62
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs27
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs18
-rw-r--r--src/WixToolset.Core.WindowsInstaller/MsiBackend.cs8
-rw-r--r--src/WixToolset.Core.WindowsInstaller/MsmBackend.cs2
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs2
9 files changed, 125 insertions, 62 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
index 9194c4c7..a7da13bb 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
@@ -39,6 +39,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
39 this.FileSystemExtensions = context.FileSystemExtensions; 39 this.FileSystemExtensions = context.FileSystemExtensions;
40 this.Intermediate = context.IntermediateRepresentation; 40 this.Intermediate = context.IntermediateRepresentation;
41 this.OutputPath = context.OutputPath; 41 this.OutputPath = context.OutputPath;
42 this.OutputPdbPath = context.OutputPdbPath;
42 this.IntermediateFolder = context.IntermediateFolder; 43 this.IntermediateFolder = context.IntermediateFolder;
43 this.Validator = validator; 44 this.Validator = validator;
44 45
@@ -71,6 +72,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
71 72
72 private string OutputPath { get; } 73 private string OutputPath { get; }
73 74
75 private string OutputPdbPath { get; }
76
74 private bool SuppressAddingValidationRows { get; } 77 private bool SuppressAddingValidationRows { get; }
75 78
76 private bool SuppressLayout { get; } 79 private bool SuppressLayout { get; }
@@ -83,7 +86,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
83 86
84 public IEnumerable<IFileTransfer> FileTransfers { get; private set; } 87 public IEnumerable<IFileTransfer> FileTransfers { get; private set; }
85 88
86 public IEnumerable<string> ContentFilePaths { get; private set; } 89 public IEnumerable<ITrackedFile> TrackedFiles { get; private set; }
87 90
88 public Pdb Pdb { get; private set; } 91 public Pdb Pdb { get; private set; }
89 92
@@ -92,6 +95,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
92 var section = this.Intermediate.Sections.Single(); 95 var section = this.Intermediate.Sections.Single();
93 96
94 var fileTransfers = new List<IFileTransfer>(); 97 var fileTransfers = new List<IFileTransfer>();
98 var trackedFiles = new List<ITrackedFile>();
95 99
96 var containsMergeModules = false; 100 var containsMergeModules = false;
97 var suppressedTableNames = new HashSet<string>(); 101 var suppressedTableNames = new HashSet<string>();
@@ -396,6 +400,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
396 command.Execute(); 400 command.Execute();
397 401
398 fileTransfers.AddRange(command.FileTransfers); 402 fileTransfers.AddRange(command.FileTransfers);
403 trackedFiles.AddRange(command.TrackedFiles);
399 } 404 }
400 405
401#if TODO_FINISH_PATCH 406#if TODO_FINISH_PATCH
@@ -416,11 +421,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
416 421
417 // Generate database file. 422 // Generate database file.
418 this.Messaging.Write(VerboseMessages.GeneratingDatabase()); 423 this.Messaging.Write(VerboseMessages.GeneratingDatabase());
419 string tempDatabaseFile = Path.Combine(this.IntermediateFolder, Path.GetFileName(this.OutputPath));
420 this.GenerateDatabase(output, tempDatabaseFile, false, false);
421 424
422 var transfer = this.BackendHelper.CreateFileTransfer(tempDatabaseFile, this.OutputPath, true, FileTransferType.Built); // note where this database needs to move in the future 425 var trackMsi = this.BackendHelper.TrackFile(this.OutputPath, TrackedFileType.Final);
423 fileTransfers.Add(transfer); 426 trackedFiles.Add(trackMsi);
427
428 var temporaryFiles = this.GenerateDatabase(output, trackMsi.Path, false, false);
429 trackedFiles.AddRange(temporaryFiles);
424 430
425 // Stop processing if an error previously occurred. 431 // Stop processing if an error previously occurred.
426 if (this.Messaging.EncounteredError) 432 if (this.Messaging.EncounteredError)
@@ -455,7 +461,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
455 var command = new MergeModulesCommand(); 461 var command = new MergeModulesCommand();
456 command.FileFacades = fileFacades; 462 command.FileFacades = fileFacades;
457 command.Output = output; 463 command.Output = output;
458 command.OutputPath = tempDatabaseFile; 464 command.OutputPath = this.OutputPath;
459 command.SuppressedTableNames = suppressedTableNames; 465 command.SuppressedTableNames = suppressedTableNames;
460 command.Execute(); 466 command.Execute();
461 } 467 }
@@ -476,7 +482,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
476 482
477 Messaging.Instance.Write(WixVerboses.ValidatingDatabase()); 483 Messaging.Instance.Write(WixVerboses.ValidatingDatabase());
478 484
479 this.Validator.Validate(tempDatabaseFile); 485 this.Validator.Validate(this.OutputPath);
480 486
481 stopwatch.Stop(); 487 stopwatch.Stop();
482 Messaging.Instance.Write(WixVerboses.ValidatedDatabase(stopwatch.ElapsedMilliseconds)); 488 Messaging.Instance.Write(WixVerboses.ValidatedDatabase(stopwatch.ElapsedMilliseconds));
@@ -498,19 +504,36 @@ namespace WixToolset.Core.WindowsInstaller.Bind
498 command.LayoutDirectory = layoutDirectory; 504 command.LayoutDirectory = layoutDirectory;
499 command.LongNamesInImage = longNames; 505 command.LongNamesInImage = longNames;
500 command.ResolveMedia = this.ResolveMedia; 506 command.ResolveMedia = this.ResolveMedia;
501 command.DatabasePath = tempDatabaseFile; 507 command.DatabasePath = this.OutputPath;
502 command.Execute(); 508 command.Execute();
503 509
504 fileTransfers.AddRange(command.FileTransfers); 510 fileTransfers.AddRange(command.FileTransfers);
511 trackedFiles.AddRange(command.TrackedFiles);
505 } 512 }
506 513
507 this.FileTransfers = fileTransfers;
508 this.ContentFilePaths = fileFacades.Select(r => r.WixFile.Source.Path).ToList();
509 this.Pdb = new Pdb { Output = output }; 514 this.Pdb = new Pdb { Output = output };
510 515
516 if (!String.IsNullOrEmpty(this.OutputPdbPath))
517 {
518 var trackPdb = this.BackendHelper.TrackFile(this.OutputPdbPath, TrackedFileType.Final);
519 trackedFiles.Add(trackPdb);
520
521 this.Pdb.Save(trackPdb.Path);
522 }
523
524 this.FileTransfers = fileTransfers;
525 // TODO: this is not sufficient to collect all Input files (for example, it misses Binary and Icon tables).
526 trackedFiles.AddRange(fileFacades.Select(f => this.BackendHelper.TrackFile(f.WixFile.Source.Path, TrackedFileType.Input, f.File.SourceLineNumbers)));
527 this.TrackedFiles = trackedFiles;
528
511 // TODO: Eventually this gets removed 529 // TODO: Eventually this gets removed
512 var intermediate = new Intermediate(this.Intermediate.Id, new[] { section }, this.Intermediate.Localizations.ToDictionary(l => l.Culture, StringComparer.OrdinalIgnoreCase), this.Intermediate.EmbedFilePaths); 530 var intermediate = new Intermediate(this.Intermediate.Id, new[] { section }, this.Intermediate.Localizations.ToDictionary(l => l.Culture, StringComparer.OrdinalIgnoreCase), this.Intermediate.EmbedFilePaths);
513 intermediate.Save(Path.ChangeExtension(this.OutputPath, "wir")); 531 var trackIntermediate = this.BackendHelper.TrackFile(Path.Combine(this.IntermediateFolder, Path.GetFileName(Path.ChangeExtension(this.OutputPath, "wir"))), TrackedFileType.Intermediate);
532 intermediate.Save(trackIntermediate.Path);
533 trackedFiles.Add(trackIntermediate);
534
535 //transfer = this.BackendHelper.CreateFileTransfer(intermediatePath, Path.ChangeExtension(this.OutputPath, "wir"), true, FileTransferType.Built);
536 //fileTransfers.Add(transfer);
514 } 537 }
515 538
516#if TODO_FINISH_PATCH 539#if TODO_FINISH_PATCH
@@ -881,9 +904,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
881 /// <param name="databaseFile">The database file to create.</param> 904 /// <param name="databaseFile">The database file to create.</param>
882 /// <param name="keepAddedColumns">Whether to keep columns added in a transform.</param> 905 /// <param name="keepAddedColumns">Whether to keep columns added in a transform.</param>
883 /// <param name="useSubdirectory">Whether to use a subdirectory based on the <paramref name="databaseFile"/> file name for intermediate files.</param> 906 /// <param name="useSubdirectory">Whether to use a subdirectory based on the <paramref name="databaseFile"/> file name for intermediate files.</param>
884 private void GenerateDatabase(Output output, string databaseFile, bool keepAddedColumns, bool useSubdirectory) 907 private IEnumerable<ITrackedFile> GenerateDatabase(Output output, string databaseFile, bool keepAddedColumns, bool useSubdirectory)
885 { 908 {
886 var command = new GenerateDatabaseCommand(); 909 var command = new GenerateDatabaseCommand();
910 command.BackendHelper = this.BackendHelper;
887 command.Extensions = this.FileSystemExtensions; 911 command.Extensions = this.FileSystemExtensions;
888 command.Output = output; 912 command.Output = output;
889 command.OutputPath = databaseFile; 913 command.OutputPath = databaseFile;
@@ -891,9 +915,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
891 command.UseSubDirectory = useSubdirectory; 915 command.UseSubDirectory = useSubdirectory;
892 command.SuppressAddingValidationRows = this.SuppressAddingValidationRows; 916 command.SuppressAddingValidationRows = this.SuppressAddingValidationRows;
893 command.TableDefinitions = this.TableDefinitions; 917 command.TableDefinitions = this.TableDefinitions;
894 command.TempFilesLocation = this.IntermediateFolder; 918 command.IntermediateFolder = this.IntermediateFolder;
895 command.Codepage = this.Codepage; 919 command.Codepage = this.Codepage;
896 command.Execute(); 920 command.Execute();
921
922 return command.GeneratedTemporaryFiles;
897 } 923 }
898 } 924 }
899} 925}
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs
index 8cb0e0de..3f5b9f05 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs
@@ -465,7 +465,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
465 command.Output = output; 465 command.Output = output;
466 command.OutputPath = outputPath; 466 command.OutputPath = outputPath;
467 command.TableDefinitions = this.TableDefinitions; 467 command.TableDefinitions = this.TableDefinitions;
468 command.TempFilesLocation = this.TempFilesLocation; 468 command.IntermediateFolder = this.TempFilesLocation;
469 command.SuppressAddingValidationRows = true; 469 command.SuppressAddingValidationRows = true;
470 command.UseSubDirectory = true; 470 command.UseSubDirectory = true;
471 command.Execute(); 471 command.Execute();
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetResolver.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetResolver.cs
index 759fa586..541dacf8 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetResolver.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetResolver.cs
@@ -48,7 +48,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
48 // to be built to and check if there is a cabinet that can be reused. 48 // to be built to and check if there is a cabinet that can be reused.
49 if (!String.IsNullOrEmpty(this.CabCachePath)) 49 if (!String.IsNullOrEmpty(this.CabCachePath))
50 { 50 {
51 string cabinetName = Path.GetFileName(cabinetPath); 51 var cabinetName = Path.GetFileName(cabinetPath);
52 resolved.Path = Path.Combine(this.CabCachePath, cabinetName); 52 resolved.Path = Path.Combine(this.CabCachePath, cabinetName);
53 53
54 if (CheckFileExists(resolved.Path)) 54 if (CheckFileExists(resolved.Path))
@@ -57,10 +57,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
57 // 1. any files are added or removed 57 // 1. any files are added or removed
58 // 2. order of files changed or names changed 58 // 2. order of files changed or names changed
59 // 3. modified time changed 59 // 3. modified time changed
60 bool cabinetValid = true; 60 var cabinetValid = true;
61 61
62 var cabinet = new Cabinet(resolved.Path); 62 var cabinet = new Cabinet(resolved.Path);
63 List<CabinetFileInfo> fileList = cabinet.Enumerate(); 63 var fileList = cabinet.Enumerate();
64 64
65 if (filesWithPath.Count() != fileList.Count) 65 if (filesWithPath.Count() != fileList.Count)
66 { 66 {
@@ -68,16 +68,16 @@ namespace WixToolset.Core.WindowsInstaller.Bind
68 } 68 }
69 else 69 else
70 { 70 {
71 int i = 0; 71 var i = 0;
72 foreach (BindFileWithPath file in filesWithPath) 72 foreach (var file in filesWithPath)
73 { 73 {
74 // First check that the file identifiers match because that is quick and easy. 74 // First check that the file identifiers match because that is quick and easy.
75 CabinetFileInfo cabFileInfo = fileList[i]; 75 var cabFileInfo = fileList[i];
76 cabinetValid = (cabFileInfo.FileId == file.Id); 76 cabinetValid = (cabFileInfo.FileId == file.Id);
77 if (cabinetValid) 77 if (cabinetValid)
78 { 78 {
79 // Still valid so ensure the file sizes are the same. 79 // Still valid so ensure the file sizes are the same.
80 FileInfo fileInfo = new FileInfo(file.Path); 80 var fileInfo = new FileInfo(file.Path);
81 cabinetValid = (cabFileInfo.Size == fileInfo.Length); 81 cabinetValid = (cabFileInfo.Size == fileInfo.Length);
82 if (cabinetValid) 82 if (cabinetValid)
83 { 83 {
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs
index ed8f0ece..a85312c4 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs
@@ -28,6 +28,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
28 28
29 private List<IFileTransfer> fileTransfers; 29 private List<IFileTransfer> fileTransfers;
30 30
31 private List<ITrackedFile> trackedFiles;
32
31 private FileSplitCabNamesCallback newCabNamesCallBack; 33 private FileSplitCabNamesCallback newCabNamesCallBack;
32 34
33 private Dictionary<string, string> lastCabinetAddedToMediaTable; // Key is First Cabinet Name, Value is Last Cabinet Added in the Split Sequence 35 private Dictionary<string, string> lastCabinetAddedToMediaTable; // Key is First Cabinet Name, Value is Last Cabinet Added in the Split Sequence
@@ -36,6 +38,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
36 { 38 {
37 this.fileTransfers = new List<IFileTransfer>(); 39 this.fileTransfers = new List<IFileTransfer>();
38 40
41 this.trackedFiles = new List<ITrackedFile>();
42
39 this.newCabNamesCallBack = this.NewCabNamesCallBack; 43 this.newCabNamesCallBack = this.NewCabNamesCallBack;
40 44
41 this.BackendHelper = backendHelper; 45 this.BackendHelper = backendHelper;
@@ -78,8 +82,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind
78 82
79 public IEnumerable<IFileTransfer> FileTransfers => this.fileTransfers; 83 public IEnumerable<IFileTransfer> FileTransfers => this.fileTransfers;
80 84
85 public IEnumerable<ITrackedFile> TrackedFiles => this.trackedFiles;
86
81 /// <param name="output">Output to generate image for.</param> 87 /// <param name="output">Output to generate image for.</param>
82 /// <param name="fileTransfers">Array of files to be transfered.</param>
83 /// <param name="layoutDirectory">The directory in which the image should be layed out.</param> 88 /// <param name="layoutDirectory">The directory in which the image should be layed out.</param>
84 /// <param name="compressed">Flag if source image should be compressed.</param> 89 /// <param name="compressed">Flag if source image should be compressed.</param>
85 /// <returns>The uncompressed file rows.</returns> 90 /// <returns>The uncompressed file rows.</returns>
@@ -119,7 +124,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
119 124
120 string cabinetDir = this.ResolveMedia(mediaTuple, mediaLayoutFolder, this.LayoutDirectory); 125 string cabinetDir = this.ResolveMedia(mediaTuple, mediaLayoutFolder, this.LayoutDirectory);
121 126
122 CabinetWorkItem cabinetWorkItem = this.CreateCabinetWorkItem(this.Output, cabinetDir, mediaTuple, compressionLevel, files, this.fileTransfers); 127 var cabinetWorkItem = this.CreateCabinetWorkItem(this.Output, cabinetDir, mediaTuple, compressionLevel, files);
123 if (null != cabinetWorkItem) 128 if (null != cabinetWorkItem)
124 { 129 {
125 cabinetBuilder.Enqueue(cabinetWorkItem); 130 cabinetBuilder.Enqueue(cabinetWorkItem);
@@ -188,9 +193,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
188 /// <param name="cabinetDir">Directory to create cabinet in.</param> 193 /// <param name="cabinetDir">Directory to create cabinet in.</param>
189 /// <param name="mediaRow">MediaRow containing information about the cabinet.</param> 194 /// <param name="mediaRow">MediaRow containing information about the cabinet.</param>
190 /// <param name="fileFacades">Collection of files in this cabinet.</param> 195 /// <param name="fileFacades">Collection of files in this cabinet.</param>
191 /// <param name="fileTransfers">Array of files to be transfered.</param>
192 /// <returns>created CabinetWorkItem object</returns> 196 /// <returns>created CabinetWorkItem object</returns>
193 private CabinetWorkItem CreateCabinetWorkItem(Output output, string cabinetDir, MediaTuple mediaRow, CompressionLevel compressionLevel, IEnumerable<FileFacade> fileFacades, List<IFileTransfer> fileTransfers) 197 private CabinetWorkItem CreateCabinetWorkItem(Output output, string cabinetDir, MediaTuple mediaRow, CompressionLevel compressionLevel, IEnumerable<FileFacade> fileFacades)
194 { 198 {
195 CabinetWorkItem cabinetWorkItem = null; 199 CabinetWorkItem cabinetWorkItem = null;
196 string tempCabinetFileX = Path.Combine(this.TempFilesLocation, mediaRow.Cabinet); 200 string tempCabinetFileX = Path.Combine(this.TempFilesLocation, mediaRow.Cabinet);
@@ -219,7 +223,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
219 223
220 var cabinetResolver = new CabinetResolver(this.CabCachePath, this.BackendExtensions); 224 var cabinetResolver = new CabinetResolver(this.CabCachePath, this.BackendExtensions);
221 225
222 ResolvedCabinet resolvedCabinet = cabinetResolver.ResolveCabinet(tempCabinetFileX, fileFacades); 226 var resolvedCabinet = cabinetResolver.ResolveCabinet(tempCabinetFileX, fileFacades);
223 227
224 // create a cabinet work item if it's not being skipped 228 // create a cabinet work item if it's not being skipped
225 if (CabinetBuildOption.BuildAndCopy == resolvedCabinet.BuildOption || CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption) 229 if (CabinetBuildOption.BuildAndCopy == resolvedCabinet.BuildOption || CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption)
@@ -248,19 +252,24 @@ namespace WixToolset.Core.WindowsInstaller.Bind
248 } 252 }
249 } 253 }
250 254
255 var trackResolvedCabinet = this.BackendHelper.TrackFile(resolvedCabinet.Path, TrackedFileType.Intermediate, mediaRow.SourceLineNumbers);
256 this.trackedFiles.Add(trackResolvedCabinet);
257
251 if (mediaRow.Cabinet.StartsWith("#", StringComparison.Ordinal)) 258 if (mediaRow.Cabinet.StartsWith("#", StringComparison.Ordinal))
252 { 259 {
253 Table streamsTable = output.EnsureTable(this.TableDefinitions["_Streams"]); 260 var streamsTable = output.EnsureTable(this.TableDefinitions["_Streams"]);
254 261
255 Row streamRow = streamsTable.CreateRow(mediaRow.SourceLineNumbers); 262 var streamRow = streamsTable.CreateRow(mediaRow.SourceLineNumbers);
256 streamRow[0] = mediaRow.Cabinet.Substring(1); 263 streamRow[0] = mediaRow.Cabinet.Substring(1);
257 streamRow[1] = resolvedCabinet.Path; 264 streamRow[1] = resolvedCabinet.Path;
258 } 265 }
259 else 266 else
260 { 267 {
261 var destinationPath = Path.Combine(cabinetDir, mediaRow.Cabinet); 268 var trackDestination = this.BackendHelper.TrackFile(Path.Combine(cabinetDir, mediaRow.Cabinet), TrackedFileType.Final, mediaRow.SourceLineNumbers);
262 var transfer = this.BackendHelper.CreateFileTransfer(resolvedCabinet.Path, destinationPath, CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption, FileTransferType.Built, mediaRow.SourceLineNumbers); 269 this.trackedFiles.Add(trackDestination);
263 fileTransfers.Add(transfer); 270
271 var transfer = this.BackendHelper.CreateFileTransfer(resolvedCabinet.Path, trackDestination.Path, resolvedCabinet.BuildOption == CabinetBuildOption.BuildAndMove, mediaRow.SourceLineNumbers);
272 this.fileTransfers.Add(transfer);
264 } 273 }
265 274
266 return cabinetWorkItem; 275 return cabinetWorkItem;
@@ -298,10 +307,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
298 /// <param name="firstCabName">The name of splitting cabinet without extention e.g. "cab1".</param> 307 /// <param name="firstCabName">The name of splitting cabinet without extention e.g. "cab1".</param>
299 /// <param name="newCabName">The name of the new cabinet that would be formed by splitting e.g. "cab1b.cab"</param> 308 /// <param name="newCabName">The name of the new cabinet that would be formed by splitting e.g. "cab1b.cab"</param>
300 /// <param name="fileToken">The file token of the first file present in the splitting cabinet</param> 309 /// <param name="fileToken">The file token of the first file present in the splitting cabinet</param>
301 internal void NewCabNamesCallBack([MarshalAs(UnmanagedType.LPWStr)]string firstCabName, [MarshalAs(UnmanagedType.LPWStr)]string newCabName, [MarshalAs(UnmanagedType.LPWStr)]string fileToken) 310 internal void NewCabNamesCallBack([MarshalAs(UnmanagedType.LPWStr)]string firstCabName, [MarshalAs(UnmanagedType.LPWStr)]string newCabinetName, [MarshalAs(UnmanagedType.LPWStr)]string fileToken)
302 { 311 {
303 // Locking Mutex here as this callback can come from Multiple Cabinet Builder Threads 312 // Locking Mutex here as this callback can come from Multiple Cabinet Builder Threads
304 Mutex mutex = new Mutex(false, "WixCabinetSplitBinderCallback"); 313 var mutex = new Mutex(false, "WixCabinetSplitBinderCallback");
305 try 314 try
306 { 315 {
307 if (!mutex.WaitOne(0, false)) // Check if you can get the lock 316 if (!mutex.WaitOne(0, false)) // Check if you can get the lock
@@ -311,19 +320,24 @@ namespace WixToolset.Core.WindowsInstaller.Bind
311 mutex.WaitOne(); // Wait on other thread 320 mutex.WaitOne(); // Wait on other thread
312 } 321 }
313 322
314 string firstCabinetName = firstCabName + ".cab"; 323 var firstCabinetName = firstCabName + ".cab";
315 string newCabinetName = newCabName; 324 var transferAdded = false; // Used for Error Handling
316 bool transferAdded = false; // Used for Error Handling
317 325
318 // Create File Transfer for new Cabinet using transfer of Base Cabinet 326 // Create File Transfer for new Cabinet using transfer of Base Cabinet
319 foreach (var transfer in this.FileTransfers) 327 foreach (var transfer in this.FileTransfers)
320 { 328 {
321 if (firstCabinetName.Equals(Path.GetFileName(transfer.Source), StringComparison.InvariantCultureIgnoreCase)) 329 if (firstCabinetName.Equals(Path.GetFileName(transfer.Source), StringComparison.InvariantCultureIgnoreCase))
322 { 330 {
323 string newCabSourcePath = Path.Combine(Path.GetDirectoryName(transfer.Source), newCabinetName); 331 var newCabSourcePath = Path.Combine(Path.GetDirectoryName(transfer.Source), newCabinetName);
324 string newCabTargetPath = Path.Combine(Path.GetDirectoryName(transfer.Destination), newCabinetName); 332 var newCabTargetPath = Path.Combine(Path.GetDirectoryName(transfer.Destination), newCabinetName);
333
334 var trackSource = this.BackendHelper.TrackFile(newCabSourcePath, TrackedFileType.Intermediate, transfer.SourceLineNumbers);
335 this.trackedFiles.Add(trackSource);
336
337 var trackTarget = this.BackendHelper.TrackFile(newCabTargetPath, TrackedFileType.Final, transfer.SourceLineNumbers);
338 this.trackedFiles.Add(trackTarget);
325 339
326 var newTransfer = this.BackendHelper.CreateFileTransfer(newCabSourcePath, newCabTargetPath, transfer.Move, FileTransferType.Built, transfer.SourceLineNumbers); 340 var newTransfer = this.BackendHelper.CreateFileTransfer(trackSource.Path, trackTarget.Path, transfer.Move, transfer.SourceLineNumbers);
327 this.fileTransfers.Add(newTransfer); 341 this.fileTransfers.Add(newTransfer);
328 342
329 transferAdded = true; 343 transferAdded = true;
@@ -338,13 +352,13 @@ namespace WixToolset.Core.WindowsInstaller.Bind
338 } 352 }
339 353
340 // Add the new Cabinets to media table using LastSequence of Base Cabinet 354 // Add the new Cabinets to media table using LastSequence of Base Cabinet
341 Table mediaTable = this.Output.Tables["Media"]; 355 var mediaTable = this.Output.Tables["Media"];
342 Table wixFileTable = this.Output.Tables["WixFile"]; 356 var wixFileTable = this.Output.Tables["WixFile"];
343 int diskIDForLastSplitCabAdded = 0; // The DiskID value for the first cab in this cabinet split chain 357 var diskIDForLastSplitCabAdded = 0; // The DiskID value for the first cab in this cabinet split chain
344 int lastSequenceForLastSplitCabAdded = 0; // The LastSequence value for the first cab in this cabinet split chain 358 var lastSequenceForLastSplitCabAdded = 0; // The LastSequence value for the first cab in this cabinet split chain
345 bool lastSplitCabinetFound = false; // Used for Error Handling 359 var lastSplitCabinetFound = false; // Used for Error Handling
346 360
347 string lastCabinetOfThisSequence = String.Empty; 361 var lastCabinetOfThisSequence = String.Empty;
348 // Get the Value of Last Cabinet Added in this split Sequence from Dictionary 362 // Get the Value of Last Cabinet Added in this split Sequence from Dictionary
349 if (!this.lastCabinetAddedToMediaTable.TryGetValue(firstCabinetName, out lastCabinetOfThisSequence)) 363 if (!this.lastCabinetAddedToMediaTable.TryGetValue(firstCabinetName, out lastCabinetOfThisSequence))
350 { 364 {
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs
index 3ab3b601..4e062696 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs
@@ -14,11 +14,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
14 using WixToolset.Core.Native; 14 using WixToolset.Core.Native;
15 using WixToolset.Data.WindowsInstaller; 15 using WixToolset.Data.WindowsInstaller;
16 using WixToolset.Extensibility.Services; 16 using WixToolset.Extensibility.Services;
17 using WixToolset.Extensibility.Data;
17 18
18 internal class GenerateDatabaseCommand 19 internal class GenerateDatabaseCommand
19 { 20 {
20 public int Codepage { private get; set; } 21 public int Codepage { private get; set; }
21 22
23 public IBackendHelper BackendHelper { private get; set; }
24
22 public IEnumerable<IFileSystemExtension> Extensions { private get; set; } 25 public IEnumerable<IFileSystemExtension> Extensions { private get; set; }
23 26
24 /// <summary> 27 /// <summary>
@@ -34,7 +37,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind
34 37
35 public TableDefinitionCollection TableDefinitions { private get; set; } 38 public TableDefinitionCollection TableDefinitions { private get; set; }
36 39
37 public string TempFilesLocation { private get; set; } 40 public string IntermediateFolder { private get; set; }
41
42 public List<ITrackedFile> GeneratedTemporaryFiles { get; } = new List<ITrackedFile>();
38 43
39 /// <summary> 44 /// <summary>
40 /// Whether to use a subdirectory based on the <paramref name="databaseFile"/> file name for intermediate files. 45 /// Whether to use a subdirectory based on the <paramref name="databaseFile"/> file name for intermediate files.
@@ -103,7 +108,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
103 } 108 }
104 109
105 // Set the base directory. 110 // Set the base directory.
106 string baseDirectory = this.TempFilesLocation; 111 var baseDirectory = this.IntermediateFolder;
107 112
108 if (this.UseSubDirectory) 113 if (this.UseSubDirectory)
109 { 114 {
@@ -114,7 +119,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
114 Directory.CreateDirectory(baseDirectory); 119 Directory.CreateDirectory(baseDirectory);
115 } 120 }
116 121
117 var idtDirectory = Path.Combine(baseDirectory, "idts"); 122 var idtDirectory = Path.Combine(baseDirectory, "_idts");
118 Directory.CreateDirectory(idtDirectory); 123 Directory.CreateDirectory(idtDirectory);
119 124
120 try 125 try
@@ -137,6 +142,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
137 this.Output.Codepage = this.Codepage; 142 this.Output.Codepage = this.Codepage;
138 } 143 }
139 144
145 Directory.CreateDirectory(Path.GetDirectoryName(this.OutputPath));
146
140 using (Database db = new Database(this.OutputPath, type)) 147 using (Database db = new Database(this.OutputPath, type))
141 { 148 {
142 // if we're not using the default codepage, import a new one into our 149 // if we're not using the default codepage, import a new one into our
@@ -185,6 +192,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind
185 var command = new CreateIdtFileCommand(this.Messaging, importTable, this.Output.Codepage, idtDirectory, this.KeepAddedColumns); 192 var command = new CreateIdtFileCommand(this.Messaging, importTable, this.Output.Codepage, idtDirectory, this.KeepAddedColumns);
186 command.Execute(); 193 command.Execute();
187 194
195 var buildOutput = this.BackendHelper.TrackFile(command.IdtPath, TrackedFileType.Temporary);
196 this.GeneratedTemporaryFiles.Add(buildOutput);
197
188 db.Import(command.IdtPath); 198 db.Import(command.IdtPath);
189 } 199 }
190 catch (WixInvalidIdtException) 200 catch (WixInvalidIdtException)
@@ -309,7 +319,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
309 { 319 {
310 foreach (SubStorage subStorage in this.Output.SubStorages) 320 foreach (SubStorage subStorage in this.Output.SubStorages)
311 { 321 {
312 string transformFile = Path.Combine(this.TempFilesLocation, String.Concat(subStorage.Name, ".mst")); 322 string transformFile = Path.Combine(this.IntermediateFolder, String.Concat(subStorage.Name, ".mst"));
313 323
314 // Bind the transform. 324 // Bind the transform.
315 this.BindTransform(subStorage.Data, transformFile); 325 this.BindTransform(subStorage.Data, transformFile);
@@ -346,7 +356,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
346 var command = new BindTransformCommand(); 356 var command = new BindTransformCommand();
347 command.Messaging = this.Messaging; 357 command.Messaging = this.Messaging;
348 command.Extensions = this.Extensions; 358 command.Extensions = this.Extensions;
349 command.TempFilesLocation = this.TempFilesLocation; 359 command.TempFilesLocation = this.IntermediateFolder;
350 command.Transform = transform; 360 command.Transform = transform;
351 command.OutputPath = outputPath; 361 command.OutputPath = outputPath;
352 command.TableDefinitions = this.TableDefinitions; 362 command.TableDefinitions = this.TableDefinitions;
@@ -356,8 +366,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
356 private void SetDatabaseCodepage(Database db, int codepage, string idtDirectory) 366 private void SetDatabaseCodepage(Database db, int codepage, string idtDirectory)
357 { 367 {
358 // write out the _ForceCodepage IDT file 368 // write out the _ForceCodepage IDT file
359 string idtPath = Path.Combine(idtDirectory, "_ForceCodepage.idt"); 369 var idtPath = Path.Combine(idtDirectory, "_ForceCodepage.idt");
360 using (StreamWriter idtFile = new StreamWriter(idtPath, false, Encoding.ASCII)) 370 using (var idtFile = new StreamWriter(idtPath, false, Encoding.ASCII))
361 { 371 {
362 idtFile.WriteLine(); // dummy column name record 372 idtFile.WriteLine(); // dummy column name record
363 idtFile.WriteLine(); // dummy column definition record 373 idtFile.WriteLine(); // dummy column definition record
@@ -365,6 +375,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind
365 idtFile.WriteLine("\t_ForceCodepage"); 375 idtFile.WriteLine("\t_ForceCodepage");
366 } 376 }
367 377
378 var trackId = this.BackendHelper.TrackFile(idtPath, TrackedFileType.Temporary);
379 this.GeneratedTemporaryFiles.Add(trackId);
380
368 // try to import the table into the MSI 381 // try to import the table into the MSI
369 try 382 try
370 { 383 {
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs
index b09f92bb..3ad74fd1 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs
@@ -43,10 +43,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
43 43
44 public IEnumerable<IFileTransfer> FileTransfers { get; private set; } 44 public IEnumerable<IFileTransfer> FileTransfers { get; private set; }
45 45
46 public IEnumerable<ITrackedFile> TrackedFiles { get; private set; }
47
46 public void Execute() 48 public void Execute()
47 { 49 {
48 var fileTransfers = new List<IFileTransfer>(); 50 var fileTransfers = new List<IFileTransfer>();
49 51
52 var trackedFiles = new List<ITrackedFile>();
53
50 var directories = new Dictionary<string, ResolvedDirectory>(); 54 var directories = new Dictionary<string, ResolvedDirectory>();
51 55
52 var mediaRows = this.Section.Tuples.OfType<MediaTuple>().ToDictionary(t => t.DiskId); 56 var mediaRows = this.Section.Tuples.OfType<MediaTuple>().ToDictionary(t => t.DiskId);
@@ -108,14 +112,26 @@ namespace WixToolset.Core.WindowsInstaller.Bind
108 112
109 // finally put together the base media layout path and the relative file layout path 113 // finally put together the base media layout path and the relative file layout path
110 var fileLayoutPath = Path.Combine(mediaLayoutDirectory, relativeFileLayoutPath); 114 var fileLayoutPath = Path.Combine(mediaLayoutDirectory, relativeFileLayoutPath);
111 var transfer = this.BackendHelper.CreateFileTransfer(facade.WixFile.Source.Path, fileLayoutPath, false, FileTransferType.Content, facade.File.SourceLineNumbers); 115
116 var transfer = this.BackendHelper.CreateFileTransfer(facade.WixFile.Source.Path, fileLayoutPath, false, facade.File.SourceLineNumbers);
112 fileTransfers.Add(transfer); 117 fileTransfers.Add(transfer);
118
119 // Track the location where the cabinet will be placed. If the transfer is
120 // redundant then then the file should not be cleaned. This is important
121 // because if the source and destination of the transfer is the same, we
122 // don't want to clean the file because we'd be deleting the original
123 // (and that would be bad).
124 var tracked = this.BackendHelper.TrackFile(transfer.Destination, TrackedFileType.Final, facade.File.SourceLineNumbers);
125 tracked.Clean = !transfer.Redundant;
126
127 trackedFiles.Add(tracked);
113 } 128 }
114 } 129 }
115 } 130 }
116 } 131 }
117 132
118 this.FileTransfers = fileTransfers; 133 this.FileTransfers = fileTransfers;
134 this.TrackedFiles = trackedFiles;
119 } 135 }
120 } 136 }
121} 137}
diff --git a/src/WixToolset.Core.WindowsInstaller/MsiBackend.cs b/src/WixToolset.Core.WindowsInstaller/MsiBackend.cs
index f72a7c66..c0c518f8 100644
--- a/src/WixToolset.Core.WindowsInstaller/MsiBackend.cs
+++ b/src/WixToolset.Core.WindowsInstaller/MsiBackend.cs
@@ -29,18 +29,12 @@ namespace WixToolset.Core.WindowsInstaller
29 var command = new BindDatabaseCommand(context, backendExtensions, validator); 29 var command = new BindDatabaseCommand(context, backendExtensions, validator);
30 command.Execute(); 30 command.Execute();
31 31
32 var result = new BindResult { FileTransfers = command.FileTransfers, ContentFilePaths = command.ContentFilePaths }; 32 var result = new BindResult { FileTransfers = command.FileTransfers, TrackedFiles = command.TrackedFiles };
33 33
34 foreach (var extension in backendExtensions) 34 foreach (var extension in backendExtensions)
35 { 35 {
36 extension.PostBackendBind(result, command.Pdb); 36 extension.PostBackendBind(result, command.Pdb);
37 } 37 }
38
39 if (!String.IsNullOrEmpty(context.OutputPdbPath))
40 {
41 command.Pdb?.Save(context.OutputPdbPath);
42 }
43
44 return result; 38 return result;
45 } 39 }
46 40
diff --git a/src/WixToolset.Core.WindowsInstaller/MsmBackend.cs b/src/WixToolset.Core.WindowsInstaller/MsmBackend.cs
index 91377b48..6c97f08d 100644
--- a/src/WixToolset.Core.WindowsInstaller/MsmBackend.cs
+++ b/src/WixToolset.Core.WindowsInstaller/MsmBackend.cs
@@ -28,7 +28,7 @@ namespace WixToolset.Core.WindowsInstaller
28 var command = new BindDatabaseCommand(context, backendExtensions, validator); 28 var command = new BindDatabaseCommand(context, backendExtensions, validator);
29 command.Execute(); 29 command.Execute();
30 30
31 var result = new BindResult { FileTransfers = command.FileTransfers, ContentFilePaths = command.ContentFilePaths }; 31 var result = new BindResult { FileTransfers = command.FileTransfers, TrackedFiles = command.TrackedFiles };
32 32
33 foreach (var extension in backendExtensions) 33 foreach (var extension in backendExtensions)
34 { 34 {
diff --git a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs
index 80401822..3c32719e 100644
--- a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs
@@ -251,7 +251,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
251 command.UseSubDirectory = false; 251 command.UseSubDirectory = false;
252 command.SuppressAddingValidationRows = true; 252 command.SuppressAddingValidationRows = true;
253 command.TableDefinitions = this.TableDefinitions; 253 command.TableDefinitions = this.TableDefinitions;
254 command.TempFilesLocation = this.IntermediateFolder; 254 command.IntermediateFolder = this.IntermediateFolder;
255 command.Codepage = -1; 255 command.Codepage = -1;
256 command.Execute(); 256 command.Execute();
257 } 257 }