@joebigelow / wix / commits / 2a27f903

Track files to enable clean builds in MSBuild

Rob Mensching committed Aug 11, 2018 at 01:06 UTC 2a27f9032aa115bc2f88d9be695d9b049db1a894
20 files changed +284 -110
src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
+1 -1
@@ -101,7 +101,7 @@ namespace WixToolset.Core.Burn
101
102 public IEnumerable<IFileTransfer> FileTransfers { get; private set; }
103
104 - public IEnumerable<string> ContentFilePaths { get; private set; }
104 + public IEnumerable<ITrackedFile> TrackedFiles { get; private set; }
105
106 public void Execute()
107 {
src/WixToolset.Core.Burn/BundleBackend.cs
+1 -1
@@ -24,7 +24,7 @@ namespace WixToolset.Core.Burn
24 //command.WixVariableResolver = context.WixVariableResolver;
25 command.Execute();
26
27 - return new BindResult { FileTransfers = command.FileTransfers, ContentFilePaths = command.ContentFilePaths };
27 + return new BindResult { FileTransfers = command.FileTransfers, TrackedFiles = command.TrackedFiles };
28 }
29
30 public bool Inscribe(IInscribeContext context)
src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
+39 -13
@@ -39,6 +39,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
39 this.FileSystemExtensions = context.FileSystemExtensions;
40 this.Intermediate = context.IntermediateRepresentation;
41 this.OutputPath = context.OutputPath;
42 + this.OutputPdbPath = context.OutputPdbPath;
43 this.IntermediateFolder = context.IntermediateFolder;
44 this.Validator = validator;
45
@@ -71,6 +72,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
72
73 private string OutputPath { get; }
74
75 + private string OutputPdbPath { get; }
76 +
77 private bool SuppressAddingValidationRows { get; }
78
79 private bool SuppressLayout { get; }
@@ -83,7 +86,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
86
87 public IEnumerable<IFileTransfer> FileTransfers { get; private set; }
88
86 - public IEnumerable<string> ContentFilePaths { get; private set; }
89 + public IEnumerable<ITrackedFile> TrackedFiles { get; private set; }
90
91 public Pdb Pdb { get; private set; }
92
@@ -92,6 +95,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
95 var section = this.Intermediate.Sections.Single();
96
97 var fileTransfers = new List<IFileTransfer>();
98 + var trackedFiles = new List<ITrackedFile>();
99
100 var containsMergeModules = false;
101 var suppressedTableNames = new HashSet<string>();
@@ -396,6 +400,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
400 command.Execute();
401
402 fileTransfers.AddRange(command.FileTransfers);
403 + trackedFiles.AddRange(command.TrackedFiles);
404 }
405
406 #if TODO_FINISH_PATCH
@@ -416,11 +421,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
421
422 // Generate database file.
423 this.Messaging.Write(VerboseMessages.GeneratingDatabase());
419 - string tempDatabaseFile = Path.Combine(this.IntermediateFolder, Path.GetFileName(this.OutputPath));
420 - this.GenerateDatabase(output, tempDatabaseFile, false, false);
424
422 - var transfer = this.BackendHelper.CreateFileTransfer(tempDatabaseFile, this.OutputPath, true, FileTransferType.Built); // note where this database needs to move in the future
423 - fileTransfers.Add(transfer);
425 + var trackMsi = this.BackendHelper.TrackFile(this.OutputPath, TrackedFileType.Final);
426 + trackedFiles.Add(trackMsi);
427 +
428 + var temporaryFiles = this.GenerateDatabase(output, trackMsi.Path, false, false);
429 + trackedFiles.AddRange(temporaryFiles);
430
431 // Stop processing if an error previously occurred.
432 if (this.Messaging.EncounteredError)
@@ -455,7 +461,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
461 var command = new MergeModulesCommand();
462 command.FileFacades = fileFacades;
463 command.Output = output;
458 - command.OutputPath = tempDatabaseFile;
464 + command.OutputPath = this.OutputPath;
465 command.SuppressedTableNames = suppressedTableNames;
466 command.Execute();
467 }
@@ -476,7 +482,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
482
483 Messaging.Instance.Write(WixVerboses.ValidatingDatabase());
484
479 - this.Validator.Validate(tempDatabaseFile);
485 + this.Validator.Validate(this.OutputPath);
486
487 stopwatch.Stop();
488 Messaging.Instance.Write(WixVerboses.ValidatedDatabase(stopwatch.ElapsedMilliseconds));
@@ -498,19 +504,36 @@ namespace WixToolset.Core.WindowsInstaller.Bind
504 command.LayoutDirectory = layoutDirectory;
505 command.LongNamesInImage = longNames;
506 command.ResolveMedia = this.ResolveMedia;
501 - command.DatabasePath = tempDatabaseFile;
507 + command.DatabasePath = this.OutputPath;
508 command.Execute();
509
510 fileTransfers.AddRange(command.FileTransfers);
511 + trackedFiles.AddRange(command.TrackedFiles);
512 }
513
507 - this.FileTransfers = fileTransfers;
508 - this.ContentFilePaths = fileFacades.Select(r => r.WixFile.Source.Path).ToList();
514 this.Pdb = new Pdb { Output = output };
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 +
529 // TODO: Eventually this gets removed
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);
537 }
538
539 #if TODO_FINISH_PATCH
@@ -881,9 +904,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
904 /// <param name="databaseFile">The database file to create.</param>
905 /// <param name="keepAddedColumns">Whether to keep columns added in a transform.</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)
908 {
909 var command = new GenerateDatabaseCommand();
910 + command.BackendHelper = this.BackendHelper;
911 command.Extensions = this.FileSystemExtensions;
912 command.Output = output;
913 command.OutputPath = databaseFile;
@@ -891,9 +915,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
915 command.UseSubDirectory = useSubdirectory;
916 command.SuppressAddingValidationRows = this.SuppressAddingValidationRows;
917 command.TableDefinitions = this.TableDefinitions;
894 - command.TempFilesLocation = this.IntermediateFolder;
918 + command.IntermediateFolder = this.IntermediateFolder;
919 command.Codepage = this.Codepage;
920 command.Execute();
921 +
922 + return command.GeneratedTemporaryFiles;
923 }
924 }
925 }
src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs
+1 -1
@@ -465,7 +465,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
465 command.Output = output;
466 command.OutputPath = outputPath;
467 command.TableDefinitions = this.TableDefinitions;
468 - command.TempFilesLocation = this.TempFilesLocation;
468 + command.IntermediateFolder = this.TempFilesLocation;
469 command.SuppressAddingValidationRows = true;
470 command.UseSubDirectory = true;
471 command.Execute();
src/WixToolset.Core.WindowsInstaller/Bind/CabinetResolver.cs
+7 -7
@@ -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.
49 if (!String.IsNullOrEmpty(this.CabCachePath))
50 {
51 - string cabinetName = Path.GetFileName(cabinetPath);
51 + var cabinetName = Path.GetFileName(cabinetPath);
52 resolved.Path = Path.Combine(this.CabCachePath, cabinetName);
53
54 if (CheckFileExists(resolved.Path))
@@ -57,10 +57,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
57 // 1. any files are added or removed
58 // 2. order of files changed or names changed
59 // 3. modified time changed
60 - bool cabinetValid = true;
60 + var cabinetValid = true;
61
62 var cabinet = new Cabinet(resolved.Path);
63 - List<CabinetFileInfo> fileList = cabinet.Enumerate();
63 + var fileList = cabinet.Enumerate();
64
65 if (filesWithPath.Count() != fileList.Count)
66 {
@@ -68,16 +68,16 @@ namespace WixToolset.Core.WindowsInstaller.Bind
68 }
69 else
70 {
71 - int i = 0;
72 - foreach (BindFileWithPath file in filesWithPath)
71 + var i = 0;
72 + foreach (var file in filesWithPath)
73 {
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);
77 if (cabinetValid)
78 {
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);
82 if (cabinetValid)
83 {
src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs
+38 -24
@@ -28,6 +28,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
28
29 private List<IFileTransfer> fileTransfers;
30
31 + private List<ITrackedFile> trackedFiles;
32 +
33 private FileSplitCabNamesCallback newCabNamesCallBack;
34
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
38 {
39 this.fileTransfers = new List<IFileTransfer>();
40
41 + this.trackedFiles = new List<ITrackedFile>();
42 +
43 this.newCabNamesCallBack = this.NewCabNamesCallBack;
44
45 this.BackendHelper = backendHelper;
@@ -78,8 +82,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind
82
83 public IEnumerable<IFileTransfer> FileTransfers => this.fileTransfers;
84
85 + public IEnumerable<ITrackedFile> TrackedFiles => this.trackedFiles;
86 +
87 /// <param name="output">Output to generate image for.</param>
82 - /// <param name="fileTransfers">Array of files to be transfered.</param>
88 /// <param name="layoutDirectory">The directory in which the image should be layed out.</param>
89 /// <param name="compressed">Flag if source image should be compressed.</param>
90 /// <returns>The uncompressed file rows.</returns>
@@ -119,7 +124,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
124
125 string cabinetDir = this.ResolveMedia(mediaTuple, mediaLayoutFolder, this.LayoutDirectory);
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);
128 if (null != cabinetWorkItem)
129 {
130 cabinetBuilder.Enqueue(cabinetWorkItem);
@@ -188,9 +193,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
193 /// <param name="cabinetDir">Directory to create cabinet in.</param>
194 /// <param name="mediaRow">MediaRow containing information about the cabinet.</param>
195 /// <param name="fileFacades">Collection of files in this cabinet.</param>
191 - /// <param name="fileTransfers">Array of files to be transfered.</param>
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)
198 {
199 CabinetWorkItem cabinetWorkItem = null;
200 string tempCabinetFileX = Path.Combine(this.TempFilesLocation, mediaRow.Cabinet);
@@ -219,7 +223,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
223
224 var cabinetResolver = new CabinetResolver(this.CabCachePath, this.BackendExtensions);
225
222 - ResolvedCabinet resolvedCabinet = cabinetResolver.ResolveCabinet(tempCabinetFileX, fileFacades);
226 + var resolvedCabinet = cabinetResolver.ResolveCabinet(tempCabinetFileX, fileFacades);
227
228 // create a cabinet work item if it's not being skipped
229 if (CabinetBuildOption.BuildAndCopy == resolvedCabinet.BuildOption || CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption)
@@ -248,19 +252,24 @@ namespace WixToolset.Core.WindowsInstaller.Bind
252 }
253 }
254
255 + var trackResolvedCabinet = this.BackendHelper.TrackFile(resolvedCabinet.Path, TrackedFileType.Intermediate, mediaRow.SourceLineNumbers);
256 + this.trackedFiles.Add(trackResolvedCabinet);
257 +
258 if (mediaRow.Cabinet.StartsWith("#", StringComparison.Ordinal))
259 {
253 - Table streamsTable = output.EnsureTable(this.TableDefinitions["_Streams"]);
260 + var streamsTable = output.EnsureTable(this.TableDefinitions["_Streams"]);
261
255 - Row streamRow = streamsTable.CreateRow(mediaRow.SourceLineNumbers);
262 + var streamRow = streamsTable.CreateRow(mediaRow.SourceLineNumbers);
263 streamRow[0] = mediaRow.Cabinet.Substring(1);
264 streamRow[1] = resolvedCabinet.Path;
265 }
266 else
267 {
261 - var destinationPath = Path.Combine(cabinetDir, mediaRow.Cabinet);
262 - var transfer = this.BackendHelper.CreateFileTransfer(resolvedCabinet.Path, destinationPath, CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption, FileTransferType.Built, mediaRow.SourceLineNumbers);
263 - fileTransfers.Add(transfer);
268 + var trackDestination = this.BackendHelper.TrackFile(Path.Combine(cabinetDir, mediaRow.Cabinet), TrackedFileType.Final, mediaRow.SourceLineNumbers);
269 + this.trackedFiles.Add(trackDestination);
270 +
271 + var transfer = this.BackendHelper.CreateFileTransfer(resolvedCabinet.Path, trackDestination.Path, resolvedCabinet.BuildOption == CabinetBuildOption.BuildAndMove, mediaRow.SourceLineNumbers);
272 + this.fileTransfers.Add(transfer);
273 }
274
275 return cabinetWorkItem;
@@ -298,10 +307,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
307 /// <param name="firstCabName">The name of splitting cabinet without extention e.g. "cab1".</param>
308 /// <param name="newCabName">The name of the new cabinet that would be formed by splitting e.g. "cab1b.cab"</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)
311 {
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");
314 try
315 {
316 if (!mutex.WaitOne(0, false)) // Check if you can get the lock
@@ -311,19 +320,24 @@ namespace WixToolset.Core.WindowsInstaller.Bind
320 mutex.WaitOne(); // Wait on other thread
321 }
322
314 - string firstCabinetName = firstCabName + ".cab";
315 - string newCabinetName = newCabName;
316 - bool transferAdded = false; // Used for Error Handling
323 + var firstCabinetName = firstCabName + ".cab";
324 + var transferAdded = false; // Used for Error Handling
325
326 // Create File Transfer for new Cabinet using transfer of Base Cabinet
327 foreach (var transfer in this.FileTransfers)
328 {
329 if (firstCabinetName.Equals(Path.GetFileName(transfer.Source), StringComparison.InvariantCultureIgnoreCase))
330 {
323 - string newCabSourcePath = Path.Combine(Path.GetDirectoryName(transfer.Source), newCabinetName);
324 - string newCabTargetPath = Path.Combine(Path.GetDirectoryName(transfer.Destination), newCabinetName);
331 + var newCabSourcePath = Path.Combine(Path.GetDirectoryName(transfer.Source), 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);
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);
341 this.fileTransfers.Add(newTransfer);
342
343 transferAdded = true;
@@ -338,13 +352,13 @@ namespace WixToolset.Core.WindowsInstaller.Bind
352 }
353
354 // Add the new Cabinets to media table using LastSequence of Base Cabinet
341 - Table mediaTable = this.Output.Tables["Media"];
342 - Table wixFileTable = this.Output.Tables["WixFile"];
343 - int 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
345 - bool lastSplitCabinetFound = false; // Used for Error Handling
355 + var mediaTable = this.Output.Tables["Media"];
356 + var wixFileTable = this.Output.Tables["WixFile"];
357 + var diskIDForLastSplitCabAdded = 0; // The DiskID 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
359 + var lastSplitCabinetFound = false; // Used for Error Handling
360
347 - string lastCabinetOfThisSequence = String.Empty;
361 + var lastCabinetOfThisSequence = String.Empty;
362 // Get the Value of Last Cabinet Added in this split Sequence from Dictionary
363 if (!this.lastCabinetAddedToMediaTable.TryGetValue(firstCabinetName, out lastCabinetOfThisSequence))
364 {
src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs
+20 -7
@@ -14,11 +14,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
14 using WixToolset.Core.Native;
15 using WixToolset.Data.WindowsInstaller;
16 using WixToolset.Extensibility.Services;
17 + using WixToolset.Extensibility.Data;
18
19 internal class GenerateDatabaseCommand
20 {
21 public int Codepage { private get; set; }
22
23 + public IBackendHelper BackendHelper { private get; set; }
24 +
25 public IEnumerable<IFileSystemExtension> Extensions { private get; set; }
26
27 /// <summary>
@@ -34,7 +37,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind
37
38 public TableDefinitionCollection TableDefinitions { private get; set; }
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>();
43
44 /// <summary>
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
108 }
109
110 // Set the base directory.
106 - string baseDirectory = this.TempFilesLocation;
111 + var baseDirectory = this.IntermediateFolder;
112
113 if (this.UseSubDirectory)
114 {
@@ -114,7 +119,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
119 Directory.CreateDirectory(baseDirectory);
120 }
121
117 - var idtDirectory = Path.Combine(baseDirectory, "idts");
122 + var idtDirectory = Path.Combine(baseDirectory, "_idts");
123 Directory.CreateDirectory(idtDirectory);
124
125 try
@@ -137,6 +142,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
142 this.Output.Codepage = this.Codepage;
143 }
144
145 + Directory.CreateDirectory(Path.GetDirectoryName(this.OutputPath));
146 +
147 using (Database db = new Database(this.OutputPath, type))
148 {
149 // if we're not using the default codepage, import a new one into our
@@ -185,6 +192,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind
192 var command = new CreateIdtFileCommand(this.Messaging, importTable, this.Output.Codepage, idtDirectory, this.KeepAddedColumns);
193 command.Execute();
194
195 + var buildOutput = this.BackendHelper.TrackFile(command.IdtPath, TrackedFileType.Temporary);
196 + this.GeneratedTemporaryFiles.Add(buildOutput);
197 +
198 db.Import(command.IdtPath);
199 }
200 catch (WixInvalidIdtException)
@@ -309,7 +319,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
319 {
320 foreach (SubStorage subStorage in this.Output.SubStorages)
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"));
323
324 // Bind the transform.
325 this.BindTransform(subStorage.Data, transformFile);
@@ -346,7 +356,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
356 var command = new BindTransformCommand();
357 command.Messaging = this.Messaging;
358 command.Extensions = this.Extensions;
349 - command.TempFilesLocation = this.TempFilesLocation;
359 + command.TempFilesLocation = this.IntermediateFolder;
360 command.Transform = transform;
361 command.OutputPath = outputPath;
362 command.TableDefinitions = this.TableDefinitions;
@@ -356,8 +366,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
366 private void SetDatabaseCodepage(Database db, int codepage, string idtDirectory)
367 {
368 // write out the _ForceCodepage IDT file
359 - string idtPath = Path.Combine(idtDirectory, "_ForceCodepage.idt");
360 - using (StreamWriter idtFile = new StreamWriter(idtPath, false, Encoding.ASCII))
369 + var idtPath = Path.Combine(idtDirectory, "_ForceCodepage.idt");
370 + using (var idtFile = new StreamWriter(idtPath, false, Encoding.ASCII))
371 {
372 idtFile.WriteLine(); // dummy column name record
373 idtFile.WriteLine(); // dummy column definition record
@@ -365,6 +375,9 @@ namespace WixToolset.Core.WindowsInstaller.Bind
375 idtFile.WriteLine("\t_ForceCodepage");
376 }
377
378 + var trackId = this.BackendHelper.TrackFile(idtPath, TrackedFileType.Temporary);
379 + this.GeneratedTemporaryFiles.Add(trackId);
380 +
381 // try to import the table into the MSI
382 try
383 {
src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs
+17 -1
@@ -43,10 +43,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
43
44 public IEnumerable<IFileTransfer> FileTransfers { get; private set; }
45
46 + public IEnumerable<ITrackedFile> TrackedFiles { get; private set; }
47 +
48 public void Execute()
49 {
50 var fileTransfers = new List<IFileTransfer>();
51
52 + var trackedFiles = new List<ITrackedFile>();
53 +
54 var directories = new Dictionary<string, ResolvedDirectory>();
55
56 var mediaRows = this.Section.Tuples.OfType<MediaTuple>().ToDictionary(t => t.DiskId);
@@ -108,14 +112,26 @@ namespace WixToolset.Core.WindowsInstaller.Bind
112
113 // finally put together the base media layout path and the relative file layout path
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);
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);
128 }
129 }
130 }
131 }
132
133 this.FileTransfers = fileTransfers;
134 + this.TrackedFiles = trackedFiles;
135 }
136 }
137 }
src/WixToolset.Core.WindowsInstaller/MsiBackend.cs
+1 -7
@@ -29,18 +29,12 @@ namespace WixToolset.Core.WindowsInstaller
29 var command = new BindDatabaseCommand(context, backendExtensions, validator);
30 command.Execute();
31
32 - var result = new BindResult { FileTransfers = command.FileTransfers, ContentFilePaths = command.ContentFilePaths };
32 + var result = new BindResult { FileTransfers = command.FileTransfers, TrackedFiles = command.TrackedFiles };
33
34 foreach (var extension in backendExtensions)
35 {
36 extension.PostBackendBind(result, command.Pdb);
37 }
38 -
39 - if (!String.IsNullOrEmpty(context.OutputPdbPath))
40 - {
41 - command.Pdb?.Save(context.OutputPdbPath);
42 - }
43 -
38 return result;
39 }
40
src/WixToolset.Core.WindowsInstaller/MsmBackend.cs
+1 -1
@@ -28,7 +28,7 @@ namespace WixToolset.Core.WindowsInstaller
28 var command = new BindDatabaseCommand(context, backendExtensions, validator);
29 command.Execute();
30
31 - var result = new BindResult { FileTransfers = command.FileTransfers, ContentFilePaths = command.ContentFilePaths };
31 + var result = new BindResult { FileTransfers = command.FileTransfers, TrackedFiles = command.TrackedFiles };
32
33 foreach (var extension in backendExtensions)
34 {
src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs
+1 -1
@@ -251,7 +251,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
251 command.UseSubDirectory = false;
252 command.SuppressAddingValidationRows = true;
253 command.TableDefinitions = this.TableDefinitions;
254 - command.TempFilesLocation = this.IntermediateFolder;
254 + command.IntermediateFolder = this.IntermediateFolder;
255 command.Codepage = -1;
256 command.Execute();
257 }
src/WixToolset.Core/CommandLine/BuildCommand.cs
+2 -1
@@ -276,8 +276,9 @@ namespace WixToolset.Core.CommandLine
276
277 {
278 var layout = new Layout(this.ServiceProvider);
279 + layout.TrackedFiles = bindResult.TrackedFiles;
280 layout.FileTransfers = bindResult.FileTransfers;
280 - layout.ContentFilePaths = bindResult.ContentFilePaths;
281 + layout.IntermediateFolder = this.IntermediateFolder;
282 layout.ContentsFile = this.ContentsFile;
283 layout.OutputsFile = this.OutputsFile;
284 layout.BuiltOutputsFile = this.BuiltOutputsFile;
src/WixToolset.Core/ExtensibilityServices/BackendHelper.cs
+8 -4
@@ -19,18 +19,17 @@ namespace WixToolset.Core.ExtensibilityServices
19
20 private IMessaging Messaging { get; }
21
22 - public IFileTransfer CreateFileTransfer(string source, string destination, bool move, FileTransferType type, SourceLineNumber sourceLineNumbers)
22 + public IFileTransfer CreateFileTransfer(string source, string destination, bool move, SourceLineNumber sourceLineNumbers = null)
23 {
24 - var sourceFullPath = GetValidatedFullPath(sourceLineNumbers, source);
24 + var sourceFullPath = this.GetValidatedFullPath(sourceLineNumbers, source);
25
26 - var destinationFullPath = GetValidatedFullPath(sourceLineNumbers, destination);
26 + var destinationFullPath = this.GetValidatedFullPath(sourceLineNumbers, destination);
27
28 return (String.IsNullOrEmpty(sourceFullPath) || String.IsNullOrEmpty(destinationFullPath)) ? null : new FileTransfer
29 {
30 Source = sourceFullPath,
31 Destination = destinationFullPath,
32 Move = move,
33 - Type = type,
33 SourceLineNumbers = sourceLineNumbers,
34 Redundant = String.Equals(sourceFullPath, destinationFullPath, StringComparison.OrdinalIgnoreCase)
35 };
@@ -41,6 +40,11 @@ namespace WixToolset.Core.ExtensibilityServices
40 return Uuid.NewUuid(namespaceGuid, value).ToString("B").ToUpperInvariant();
41 }
42
43 + public ITrackedFile TrackFile(string path, TrackedFileType type, SourceLineNumber sourceLineNumbers = null)
44 + {
45 + return new TrackedFile(path, type, sourceLineNumbers);
46 + }
47 +
48 private string GetValidatedFullPath(SourceLineNumber sourceLineNumbers, string path)
49 {
50 try
src/WixToolset.Core/FileTransfer.cs
-2
@@ -15,8 +15,6 @@ namespace WixToolset.Core
15
16 public SourceLineNumber SourceLineNumbers { get; set; }
17
18 - public FileTransferType Type { get; set; }
19 -
18 public bool Redundant { get; set; }
19 }
20 }
src/WixToolset.Core/Layout.cs
+111 -29
@@ -28,9 +28,11 @@ namespace WixToolset.Core
28
29 private IMessaging Messaging { get; }
30
31 + public IEnumerable<ITrackedFile> TrackedFiles { get; set; }
32 +
33 public IEnumerable<IFileTransfer> FileTransfers { get; set; }
34
33 - public IEnumerable<string> ContentFilePaths { get; set; }
35 + public string IntermediateFolder { get; set; }
36
37 public string ContentsFile { get; set; }
38
@@ -46,8 +48,8 @@ namespace WixToolset.Core
48
49 var context = this.ServiceProvider.GetService<ILayoutContext>();
50 context.Extensions = extensionManager.Create<ILayoutExtension>();
51 + context.TrackedFiles = this.TrackedFiles;
52 context.FileTransfers = this.FileTransfers;
50 - context.ContentFilePaths = this.ContentFilePaths;
53 context.ContentsFile = this.ContentsFile;
54 context.OutputsFile = this.OutputsFile;
55 context.BuiltOutputsFile = this.BuiltOutputsFile;
@@ -71,24 +73,29 @@ namespace WixToolset.Core
73 var command = new TransferFilesCommand(this.Messaging, context.Extensions, context.FileTransfers, context.SuppressAclReset);
74 command.Execute();
75 }
76 +
77 + if (context.TrackedFiles != null)
78 + {
79 + this.CleanTempFiles(context.TrackedFiles);
80 + }
81 }
82 finally
83 {
77 - if (!String.IsNullOrEmpty(context.ContentsFile) && context.ContentFilePaths != null)
84 + if (context.TrackedFiles != null)
85 {
79 - this.CreateContentsFile(context.ContentsFile, context.ContentFilePaths);
80 - }
86 + if (!String.IsNullOrEmpty(context.ContentsFile))
87 + {
88 + this.CreateContentsFile(context.ContentsFile, context.TrackedFiles);
89 + }
90
82 - if (context.FileTransfers != null)
83 - {
91 if (!String.IsNullOrEmpty(context.OutputsFile))
92 {
86 - this.CreateOutputsFile(context.OutputsFile, context.FileTransfers);
93 + this.CreateOutputsFile(context.OutputsFile, context.TrackedFiles);
94 }
95
96 if (!String.IsNullOrEmpty(context.BuiltOutputsFile))
97 {
91 - this.CreateBuiltOutputsFile(context.BuiltOutputsFile, context.FileTransfers);
98 + this.CreateBuiltOutputsFile(context.BuiltOutputsFile, context.TrackedFiles);
99 }
100 }
101 }
@@ -105,16 +112,23 @@ namespace WixToolset.Core
112 /// </summary>
113 /// <param name="path">Path to write file.</param>
114 /// <param name="contentFilePaths">Collection of paths to content files that will be written to file.</param>
108 - private void CreateContentsFile(string path, IEnumerable<string> contentFilePaths)
115 + private void CreateContentsFile(string path, IEnumerable<ITrackedFile> trackedFiles)
116 {
117 + var uniqueInputFilePaths = new SortedSet<string>(trackedFiles.Where(t => t.Type == TrackedFileType.Input).Select(t => t.Path), StringComparer.OrdinalIgnoreCase);
118 +
119 + if (!uniqueInputFilePaths.Any())
120 + {
121 + return;
122 + }
123 +
124 var directory = Path.GetDirectoryName(path);
125 Directory.CreateDirectory(directory);
126
127 using (var contents = new StreamWriter(path, false))
128 {
115 - foreach (string contentPath in contentFilePaths)
129 + foreach (string inputPath in uniqueInputFilePaths)
130 {
117 - contents.WriteLine(contentPath);
131 + contents.WriteLine(inputPath);
132 }
133 }
134 }
@@ -124,22 +138,28 @@ namespace WixToolset.Core
138 /// </summary>
139 /// <param name="path">Path to write file.</param>
140 /// <param name="fileTransfers">Collection of files that were transferred to the output directory.</param>
127 - private void CreateOutputsFile(string path, IEnumerable<IFileTransfer> fileTransfers)
141 + private void CreateOutputsFile(string path, IEnumerable<ITrackedFile> trackedFiles)
142 {
143 + var uniqueOutputPaths = new SortedSet<string>(trackedFiles.Where(t => t.Clean).Select(t => t.Path), StringComparer.OrdinalIgnoreCase);
144 +
145 + if (!uniqueOutputPaths.Any())
146 + {
147 + return;
148 + }
149 +
150 var directory = Path.GetDirectoryName(path);
151 Directory.CreateDirectory(directory);
152
153 using (var outputs = new StreamWriter(path, false))
154 {
134 - foreach (var fileTransfer in fileTransfers)
155 + //// Don't list files where the source is the same as the destination since
156 + //// that might be the only place the file exists. The outputs file is often
157 + //// used to delete stuff and losing the original source would be bad.
158 + //var uniqueOutputPaths = new SortedSet<string>(fileTransfers.Where(ft => !ft.Redundant).Select(ft => ft.Destination), StringComparer.OrdinalIgnoreCase);
159 +
160 + foreach (var outputPath in uniqueOutputPaths)
161 {
136 - // Don't list files where the source is the same as the destination since
137 - // that might be the only place the file exists. The outputs file is often
138 - // used to delete stuff and losing the original source would be bad.
139 - if (!fileTransfer.Redundant)
140 - {
141 - outputs.WriteLine(fileTransfer.Destination);
142 - }
162 + outputs.WriteLine(outputPath);
163 }
164 }
165 }
@@ -149,21 +169,83 @@ namespace WixToolset.Core
169 /// </summary>
170 /// <param name="path">Path to write file.</param>
171 /// <param name="fileTransfers">Collection of files that were transferred to the output directory.</param>
152 - private void CreateBuiltOutputsFile(string path, IEnumerable<IFileTransfer> fileTransfers)
172 + private void CreateBuiltOutputsFile(string path, IEnumerable<ITrackedFile> trackedFiles)
173 {
174 + var uniqueBuiltPaths = new SortedSet<string>(trackedFiles.Where(t => t.Type == TrackedFileType.Final).Select(t => t.Path), StringComparer.OrdinalIgnoreCase);
175 +
176 + if (!uniqueBuiltPaths.Any())
177 + {
178 + return;
179 + }
180 +
181 var directory = Path.GetDirectoryName(path);
182 Directory.CreateDirectory(directory);
183
184 using (var outputs = new StreamWriter(path, false))
185 {
159 - foreach (var fileTransfer in fileTransfers)
186 + foreach (var builtPath in uniqueBuiltPaths)
187 {
161 - // Only write the built file transfers. Also, skip redundant
162 - // files for the same reason spelled out in this.CreateOutputsFile().
163 - if (fileTransfer.Type == FileTransferType.Built && !fileTransfer.Redundant)
164 - {
165 - outputs.WriteLine(fileTransfer.Destination);
166 - }
188 + outputs.WriteLine(builtPath);
189 + }
190 + }
191 + }
192 +
193 + private void CleanTempFiles(IEnumerable<ITrackedFile> trackedFiles)
194 + {
195 + var uniqueTempPaths = new SortedSet<string>(trackedFiles.Where(t => t.Type == TrackedFileType.Temporary).Select(t => t.Path), StringComparer.OrdinalIgnoreCase);
196 +
197 + if (!uniqueTempPaths.Any())
198 + {
199 + return;
200 + }
201 +
202 + var uniqueFolders = new SortedSet<string>(StringComparer.OrdinalIgnoreCase)
203 + {
204 + this.IntermediateFolder
205 + };
206 +
207 + // Clean up temp files.
208 + foreach (var tempPath in uniqueTempPaths)
209 + {
210 + try
211 + {
212 + this.SplitUniqueFolders(tempPath, uniqueFolders);
213 +
214 + File.Delete(tempPath);
215 + }
216 + catch // delete is best effort.
217 + {
218 + }
219 + }
220 +
221 + // Clean up empty temp folders.
222 + foreach (var folder in uniqueFolders.Reverse())
223 + {
224 + try
225 + {
226 + Directory.Delete(folder);
227 + }
228 + catch // delete is best effort.
229 + {
230 + }
231 + }
232 + }
233 +
234 + private void SplitUniqueFolders(string tempPath, SortedSet<string> uniqueFolders)
235 + {
236 + if (tempPath.StartsWith(this.IntermediateFolder, StringComparison.OrdinalIgnoreCase))
237 + {
238 + var folder = Path.GetDirectoryName(tempPath).Substring(this.IntermediateFolder.Length);
239 +
240 + var parts = folder.Split(new[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries);
241 +
242 + folder = this.IntermediateFolder;
243 +
244 + foreach (var part in parts)
245 + {
246 + folder = Path.Combine(folder, part);
247 +
248 + uniqueFolders.Add(folder);
249 }
250 }
251 }
src/WixToolset.Core/LayoutContext.cs
+1 -1
@@ -22,7 +22,7 @@ namespace WixToolset.Core
22
23 public IEnumerable<IFileTransfer> FileTransfers { get; set; }
24
25 - public IEnumerable<string> ContentFilePaths { get; set; }
25 + public IEnumerable<ITrackedFile> TrackedFiles { get; set; }
26
27 public string OutputPdbPath { get; set; }
28
src/WixToolset.Core/TrackedFile.cs new
+26
@@ -0,0 +1,26 @@
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
4 +{
5 + using WixToolset.Data;
6 + using WixToolset.Extensibility.Data;
7 +
8 + internal class TrackedFile : ITrackedFile
9 + {
10 + public TrackedFile(string path, TrackedFileType type, SourceLineNumber sourceLineNumbers)
11 + {
12 + this.Path = path;
13 + this.Type = type;
14 + this.SourceLineNumbers = sourceLineNumbers;
15 + this.Clean = (type == TrackedFileType.Intermediate || type == TrackedFileType.Final);
16 + }
17 +
18 + public bool Clean { get; set; }
19 +
20 + public string Path { get; set; }
21 +
22 + public SourceLineNumber SourceLineNumbers { get; set; }
23 +
24 + public TrackedFileType Type { get; set; }
25 + }
26 +}
src/test/WixToolsetTest.CoreIntegration/ExtensionFixture.cs
+2 -2
@@ -56,7 +56,7 @@ namespace WixToolsetTest.CoreIntegration
56 Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\extest.wixpdb")));
57 Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\MsiPackage\example.txt")));
58
59 - var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\extest.wir"));
59 + var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"extest.wir"));
60 var section = intermediate.Sections.Single();
61
62 var wixFile = section.Tuples.OfType<WixFileTuple>().Single();
@@ -95,7 +95,7 @@ namespace WixToolsetTest.CoreIntegration
95
96 Assert.Equal(0, result);
97
98 - var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\extest.wir"));
98 + var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"extest.wir"));
99 var section = intermediate.Sections.Single();
100
101 var property = section.Tuples.OfType<PropertyTuple>().Where(p => p.Id.Id == "ExampleProperty").Single();
src/test/WixToolsetTest.CoreIntegration/MsiFixture.cs
+6 -6
@@ -39,7 +39,7 @@ namespace WixToolsetTest.CoreIntegration
39 Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.wixpdb")));
40 Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\MsiPackage\test.txt")));
41
42 - var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wir"));
42 + var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"test.wir"));
43 var section = intermediate.Sections.Single();
44
45 var wixFile = section.Tuples.OfType<WixFileTuple>().Single();
@@ -74,7 +74,7 @@ namespace WixToolsetTest.CoreIntegration
74 Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\example.cab")));
75 Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.wixpdb")));
76
77 - var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\test.wir"));
77 + var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"test.wir"));
78 var section = intermediate.Sections.Single();
79
80 var wixFile = section.Tuples.OfType<WixFileTuple>().Single();
@@ -264,7 +264,7 @@ namespace WixToolsetTest.CoreIntegration
264 Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.msm")));
265 Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.wixpdb")));
266
267 - var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\test.wir"));
267 + var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"test.wir"));
268 var section = intermediate.Sections.Single();
269
270 var wixFile = section.Tuples.OfType<WixFileTuple>().Single();
@@ -299,7 +299,7 @@ namespace WixToolsetTest.CoreIntegration
299 Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.wixpdb")));
300 Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\MsiPackage\test.txt")));
301
302 - var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\test.wir"));
302 + var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"test.wir"));
303 var section = intermediate.Sections.Single();
304
305 var wixFile = section.Tuples.OfType<WixFileTuple>().Single();
@@ -399,7 +399,7 @@ namespace WixToolsetTest.CoreIntegration
399 Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.wixpdb")));
400 Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\MsiPackage\test.txt")));
401
402 - var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wir"));
402 + var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"test.wir"));
403 var section = intermediate.Sections.Single();
404
405 var wixFile = section.Tuples.OfType<WixFileTuple>().Single();
@@ -435,7 +435,7 @@ namespace WixToolsetTest.CoreIntegration
435 Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.wixpdb")));
436 Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\AssemblyMsiPackage\candle.exe")));
437
438 - var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wir"));
438 + var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"test.wir"));
439 var section = intermediate.Sections.Single();
440
441 var wixFile = section.Tuples.OfType<WixFileTuple>().Single();
src/test/WixToolsetTest.CoreIntegration/WixiplFixture.cs
+1 -1
@@ -43,7 +43,7 @@ namespace WixToolsetTest.CoreIntegration
43 }, out var messagesBind);
44 Assert.Equal(0, result);
45
46 - var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"bin\test.wir"));
46 + var intermediate = Intermediate.Load(Path.Combine(baseFolder, @"obj\test.wir"));
47 var section = intermediate.Sections.Single();
48
49 var wixFile = section.Tuples.OfType<WixFileTuple>().Single();