@joebigelow / wix-1 / commits / 9a18c230

Use file system abstraction to handle retries automatically

Fixes 4791

Rob Mensching committed Oct 4, 2022 at 10:44 UTC 9a18c230cfd88996b43c8ff7c59a195fb34ed3cf
24 files changed +143 -127
src/api/wix/WixToolset.Extensibility/Services/IFileSystem.cs
+10
@@ -3,6 +3,7 @@
3 namespace WixToolset.Extensibility.Services
4 {
5 using System;
6 + using System.IO;
7
8 /// <summary>
9 /// Abstracts basic file system operations.
@@ -32,6 +33,15 @@ namespace WixToolset.Extensibility.Services
33 /// <param name="destination">The destination file.</param>
34 void MoveFile(string source, string destination);
35
36 + /// <summary>
37 + /// Opens a file.
38 + /// </summary>
39 + /// <param name="path">The file to open.</param>
40 + /// <param name="mode">A System.IO.FileMode value that specifies whether a file is created if one does not exist, and determines whether the contents of existing files are retained or overwritten.</param>
41 + /// <param name="access">A System.IO.FileAccess value that specifies the operations that can be performed on the file.</param>
42 + /// <param name="share">A System.IO.FileShare value specifying the type of access other threads have to the file.</param>
43 + FileStream OpenFile(string path, FileMode mode, FileAccess access, FileShare share);
44 +
45 /// <summary>
46 /// Executes an action and retries on any exception a few times with short pause
47 /// between each attempt. Primarily intended for use with file system operations
src/wix/WixToolset.Core.Burn/Bundles/BurnReader.cs
+3 -3
@@ -56,7 +56,7 @@ namespace WixToolset.Core.Burn.Bundles
56 /// <returns>Burn reader.</returns>
57 public static BurnReader Open(IMessaging messaging, IFileSystem fileSystem, string fileExe)
58 {
59 - var binaryReader = new BinaryReader(File.Open(fileExe, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete));
59 + var binaryReader = new BinaryReader(fileSystem.OpenFile(fileExe, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete));
60 var reader = new BurnReader(messaging, fileSystem, fileExe)
61 {
62 binaryReader = binaryReader,
@@ -92,7 +92,7 @@ namespace WixToolset.Core.Burn.Bundles
92 var uxContainerSlot = this.AttachedContainers[0];
93
94 this.binaryReader.BaseStream.Seek(this.UXAddress, SeekOrigin.Begin);
95 - using (Stream tempCab = File.Open(tempCabPath, FileMode.Create, FileAccess.Write))
95 + using (Stream tempCab = this.fileSystem.OpenFile(tempCabPath, FileMode.Create, FileAccess.Write, FileShare.Read))
96 {
97 BurnCommon.CopyStream(this.binaryReader.BaseStream, tempCab, (int)uxContainerSlot.Size);
98 }
@@ -169,7 +169,7 @@ namespace WixToolset.Core.Burn.Bundles
169 var tempCabPath = Path.Combine(tempDirectory, $"a{i}.cab");
170
171 this.binaryReader.BaseStream.Seek(nextAddress, SeekOrigin.Begin);
172 - using (Stream tempCab = File.Open(tempCabPath, FileMode.Create, FileAccess.Write))
172 + using (Stream tempCab = this.fileSystem.OpenFile(tempCabPath, FileMode.Create, FileAccess.Write, FileShare.Read))
173 {
174 BurnCommon.CopyStream(this.binaryReader.BaseStream, tempCab, (int)cntnr.Size);
175 }
src/wix/WixToolset.Core.Burn/Bundles/BurnWriter.cs
+11 -13
@@ -24,35 +24,33 @@ namespace WixToolset.Core.Burn.Bundles
24 {
25 private bool disposed;
26 private BinaryWriter binaryWriter;
27 + private readonly IFileSystem fileSystem;
28
28 - /// <summary>
29 - /// Creates a BurnWriter for re-writing a PE file.
30 - /// </summary>
31 - /// <param name="messaging"></param>
32 - /// <param name="fileExe">File to modify in-place.</param>
33 - private BurnWriter(IMessaging messaging, string fileExe)
29 + private BurnWriter(IMessaging messaging, IFileSystem fileSystem, string fileExe)
30 : base(messaging, fileExe)
31 {
32 + this.fileSystem = fileSystem;
33 }
34
35 /// <summary>
36 /// Opens a Burn writer.
37 /// </summary>
41 - /// <param name="messaging"></param>
38 + /// <param name="messaging">Messaging system.</param>
39 + /// <param name="fileSystem">File system abstraction.</param>
40 /// <param name="fileExe">Path to file.</param>
41 /// <returns>Burn writer.</returns>
44 - public static BurnWriter Open(IMessaging messaging, string fileExe)
42 + public static BurnWriter Open(IMessaging messaging, IFileSystem fileSystem, string fileExe)
43 {
46 - var writer = new BurnWriter(messaging, fileExe);
44 + var writer = new BurnWriter(messaging, fileSystem, fileExe);
45
48 - using (var binaryReader = new BinaryReader(File.Open(fileExe, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)))
46 + using (var binaryReader = new BinaryReader(fileSystem.OpenFile(fileExe, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)))
47 {
48 writer.Initialize(binaryReader);
49 }
50
51 if (!writer.Invalid)
52 {
55 - writer.binaryWriter = new BinaryWriter(File.Open(fileExe, FileMode.Open, FileAccess.ReadWrite, FileShare.Read | FileShare.Delete));
53 + writer.binaryWriter = new BinaryWriter(fileSystem.OpenFile(fileExe, FileMode.Open, FileAccess.ReadWrite, FileShare.Read | FileShare.Delete));
54 }
55
56 return writer;
@@ -109,7 +107,7 @@ namespace WixToolset.Core.Burn.Bundles
107 /// <returns>true if the container data is successfully appended; false otherwise</returns>
108 public bool AppendContainer(string fileContainer, BurnCommon.Container container)
109 {
112 - using (var reader = File.OpenRead(fileContainer))
110 + using (var reader = this.fileSystem.OpenFile(fileContainer, FileMode.Open, FileAccess.Read, FileShare.Read))
111 {
112 return this.AppendContainer(reader, reader.Length, container);
113 }
@@ -158,7 +156,7 @@ namespace WixToolset.Core.Burn.Bundles
156 public bool AppendContainer(Stream containerStream, long containerSize, BurnCommon.Container container)
157 {
158 var containerCount = (uint)this.AttachedContainers.Count;
161 - uint burnSectionOffsetSize = BURN_SECTION_OFFSET_UXSIZE + (containerCount * sizeof(uint));
159 + var burnSectionOffsetSize = BURN_SECTION_OFFSET_UXSIZE + (containerCount * sizeof(uint));
160 var containerSlot = new ContainerSlot((uint)containerSize);
161
162 switch (container)
src/wix/WixToolset.Core.Burn/Bundles/CreateBundleExeCommand.cs
+1 -1
@@ -82,7 +82,7 @@ namespace WixToolset.Core.Burn.Bundles
82
83 // Update the .wixburn section to point to at the UX and attached container(s) then attach the containers
84 // if they should be attached.
85 - using (var writer = BurnWriter.Open(this.Messaging, bundleTempPath))
85 + using (var writer = BurnWriter.Open(this.Messaging, this.FileSystem, bundleTempPath))
86 {
87 var burnStubFile = new FileInfo(bundleTempPath);
88 writer.InitializeBundleSectionData(burnStubFile.Length, this.BundleSymbol.BundleId);
src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleCommand.cs
+1 -1
@@ -40,7 +40,7 @@ namespace WixToolset.Core.Burn.Inscribe
40 {
41 this.FileSystem.CopyFile(this.SignedEngineFile, tempFile, allowHardlink: false);
42
43 - using (var writer = BurnWriter.Open(this.Messaging, tempFile))
43 + using (var writer = BurnWriter.Open(this.Messaging, this.FileSystem, tempFile))
44 {
45 inscribed = writer.ReattachContainers(reader);
46 }
src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleEngineCommand.cs
+1 -1
@@ -33,7 +33,7 @@ namespace WixToolset.Core.Burn.Inscribe
33 var tempFile = Path.Combine(this.IntermediateFolder, "bundle_engine_unsigned.exe");
34
35 using (var reader = BurnReader.Open(this.Messaging, this.FileSystem, this.InputFilePath))
36 - using (var writer = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.Read | FileShare.Delete))
36 + using (var writer = this.FileSystem.OpenFile(tempFile, FileMode.Create, FileAccess.Write, FileShare.Read | FileShare.Delete))
37 {
38 reader.Stream.Seek(0, SeekOrigin.Begin);
39
src/wix/WixToolset.Core.WindowsInstaller/Bind/AssemblyNameReader.cs
+3 -2
@@ -11,14 +11,15 @@ namespace WixToolset.Core.WindowsInstaller.Bind
11 using System.Xml;
12 using System.Xml.XPath;
13 using WixToolset.Data;
14 + using WixToolset.Extensibility.Services;
15
16 internal static class AssemblyNameReader
17 {
17 - public static AssemblyName ReadAssembly(SourceLineNumber sourceLineNumbers, string assemblyPath, string fileVersion)
18 + public static AssemblyName ReadAssembly(IFileSystem fileSystem, SourceLineNumber sourceLineNumbers, string assemblyPath, string fileVersion)
19 {
20 try
21 {
21 - using (var stream = File.OpenRead(assemblyPath))
22 + using (var stream = fileSystem.OpenFile(assemblyPath, FileMode.Open, FileAccess.Read, FileShare.Read))
23 using (var peReader = new PEReader(stream))
24 {
25 var reader = peReader.GetMetadataReader();
src/wix/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
+9 -7
@@ -28,15 +28,15 @@ namespace WixToolset.Core.WindowsInstaller.Bind
28 this.Messaging = context.ServiceProvider.GetService<IMessaging>();
29
30 this.WindowsInstallerBackendHelper = context.ServiceProvider.GetService<IWindowsInstallerBackendHelper>();
31 -
32 - this.PathResolver = this.ServiceProvider.GetService<IPathResolver>();
31 + this.FileSystem = context.ServiceProvider.GetService<IFileSystem>();
32 + this.PathResolver = context.ServiceProvider.GetService<IPathResolver>();
33
34 this.CabbingThreadCount = context.CabbingThreadCount;
35 this.CabCachePath = context.CabCachePath;
36 this.DefaultCompressionLevel = context.DefaultCompressionLevel;
37 this.DelayedFields = context.DelayedFields;
38 this.ExpectedEmbeddedFiles = context.ExpectedEmbeddedFiles;
39 - this.FileSystemManager = new FileSystemManager(context.FileSystemExtensions);
39 + this.FileSystemManager = new FileSystemManager(this.FileSystem, context.FileSystemExtensions);
40 this.Intermediate = context.IntermediateRepresentation;
41 this.IntermediateFolder = context.IntermediateFolder;
42 this.OutputPath = context.OutputPath;
@@ -52,12 +52,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
52 this.BackendExtensions = backendExtension;
53 }
54
55 - public IServiceProvider ServiceProvider { get; }
55 + private IServiceProvider ServiceProvider { get; }
56
57 private IMessaging Messaging { get; }
58
59 private IWindowsInstallerBackendHelper WindowsInstallerBackendHelper { get; }
60
61 + private IFileSystem FileSystem { get; }
62 +
63 private IPathResolver PathResolver { get; }
64
65 private int CabbingThreadCount { get; }
@@ -279,7 +281,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
281
282 // Gather information about files that do not come from merge modules.
283 {
282 - var command = new UpdateFileFacadesCommand(this.Messaging, section, allFileFacades, fileFacadesFromIntermediate, variableCache, overwriteHash: true);
284 + var command = new UpdateFileFacadesCommand(this.Messaging, this.FileSystem, section, allFileFacades, fileFacadesFromIntermediate, variableCache, overwriteHash: true);
285 command.Execute();
286 }
287
@@ -323,7 +325,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
325 {
326 var updatedFacades = reresolvedFiles.Select(f => allFileFacades.First(ff => ff.Id == f.Id?.Id));
327
326 - var command = new UpdateFileFacadesCommand(this.Messaging, section, allFileFacades, updatedFacades, variableCache, overwriteHash: false);
328 + var command = new UpdateFileFacadesCommand(this.Messaging, this.FileSystem, section, allFileFacades, updatedFacades, variableCache, overwriteHash: false);
329 command.Execute();
330 }
331 }
@@ -461,7 +463,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
463 var trackMsi = this.WindowsInstallerBackendHelper.TrackFile(this.OutputPath, TrackedFileType.BuiltTargetOutput);
464 trackedFiles.Add(trackMsi);
465
464 - var command = new GenerateDatabaseCommand(this.Messaging, this.WindowsInstallerBackendHelper, this.FileSystemManager, data, trackMsi.Path, tableDefinitions, this.IntermediateFolder, keepAddedColumns: false, this.SuppressAddingValidationRows, useSubdirectory: false);
466 + var command = new GenerateDatabaseCommand(this.Messaging, this.WindowsInstallerBackendHelper, this.FileSystem, this.FileSystemManager, data, trackMsi.Path, tableDefinitions, this.IntermediateFolder, keepAddedColumns: false, this.SuppressAddingValidationRows, useSubdirectory: false);
467 command.Execute();
468
469 trackedFiles.AddRange(command.GeneratedTemporaryFiles);
src/wix/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs
+6 -3
@@ -13,10 +13,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
13
14 internal class BindTransformCommand
15 {
16 - public BindTransformCommand(IMessaging messaging, IBackendHelper backendHelper, FileSystemManager fileSystemManager, string intermediateFolder, WindowsInstallerData transform, string outputPath, TableDefinitionCollection tableDefinitions)
16 + public BindTransformCommand(IMessaging messaging, IBackendHelper backendHelper, IFileSystem fileSystem, FileSystemManager fileSystemManager, string intermediateFolder, WindowsInstallerData transform, string outputPath, TableDefinitionCollection tableDefinitions)
17 {
18 this.Messaging = messaging;
19 this.BackendHelper = backendHelper;
20 + this.FileSystem = fileSystem;
21 this.FileSystemManager = fileSystemManager;
22 this.IntermediateFolder = intermediateFolder;
23 this.Transform = transform;
@@ -28,6 +29,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
29
30 private IBackendHelper BackendHelper { get; }
31
32 + private IFileSystem FileSystem { get; }
33 +
34 private FileSystemManager FileSystemManager { get; }
35
36 private TableDefinitionCollection TableDefinitions { get; }
@@ -398,7 +401,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
401 {
402 if (!String.IsNullOrEmpty(emptyFile))
403 {
401 - using (var fileStream = File.Create(emptyFile))
404 + using (var fileStream = this.FileSystem.OpenFile(emptyFile, FileMode.Create, FileAccess.Write, FileShare.None))
405 {
406 }
407 }
@@ -434,7 +437,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
437
438 private void GenerateDatabase(WindowsInstallerData output, string outputPath, bool keepAddedColumns)
439 {
437 - var command = new GenerateDatabaseCommand(this.Messaging, this.BackendHelper, this.FileSystemManager, output, outputPath, this.TableDefinitions, this.IntermediateFolder, keepAddedColumns, suppressAddingValidationRows: true, useSubdirectory: true);
440 + var command = new GenerateDatabaseCommand(this.Messaging, this.BackendHelper, this.FileSystem, this.FileSystemManager, output, outputPath, this.TableDefinitions, this.IntermediateFolder, keepAddedColumns, suppressAddingValidationRows: true, useSubdirectory: true);
441 command.Execute();
442 }
443 }
src/wix/WixToolset.Core.WindowsInstaller/Bind/CreatePatchTransformsCommand.cs
+5 -2
@@ -16,10 +16,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
16
17 internal class CreatePatchTransformsCommand
18 {
19 - public CreatePatchTransformsCommand(IMessaging messaging, IBackendHelper backendHelper, IPathResolver pathResolver, IFileResolver fileResolver, IReadOnlyCollection<IResolverExtension> resolverExtensions, IReadOnlyCollection<IWindowsInstallerBackendBinderExtension> backendExtensions, Intermediate intermediate, string intermediateFolder, IReadOnlyCollection<IBindPath> bindPaths)
19 + public CreatePatchTransformsCommand(IMessaging messaging, IBackendHelper backendHelper, IFileSystem fileSystem, IPathResolver pathResolver, IFileResolver fileResolver, IReadOnlyCollection<IResolverExtension> resolverExtensions, IReadOnlyCollection<IWindowsInstallerBackendBinderExtension> backendExtensions, Intermediate intermediate, string intermediateFolder, IReadOnlyCollection<IBindPath> bindPaths)
20 {
21 this.Messaging = messaging;
22 this.BackendHelper = backendHelper;
23 + this.FileSystem = fileSystem;
24 this.PathResolver = pathResolver;
25 this.FileResolver = fileResolver;
26 this.ResolverExtensions = resolverExtensions;
@@ -33,6 +34,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
34
35 private IBackendHelper BackendHelper { get; }
36
37 + private IFileSystem FileSystem { get; }
38 +
39 private IPathResolver PathResolver { get; }
40
41 private IFileResolver FileResolver { get; }
@@ -105,7 +108,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
108 var exportBasePath = Path.Combine(this.IntermediateFolder, stageFolder);
109 var extractFilesFolder = Path.Combine(exportBasePath, "File");
110
108 - var command = new UnbindDatabaseCommand(this.Messaging, this.BackendHelper, this.PathResolver, path, null, OutputType.Product, exportBasePath, extractFilesFolder, this.IntermediateFolder, enableDemodularization: false, skipSummaryInfo: false);
111 + var command = new UnbindDatabaseCommand(this.Messaging, this.BackendHelper, this.FileSystem, this.PathResolver, path, null, OutputType.Product, exportBasePath, extractFilesFolder, this.IntermediateFolder, enableDemodularization: false, skipSummaryInfo: false);
112 data = command.Execute();
113 }
114
src/wix/WixToolset.Core.WindowsInstaller/Bind/FileSystemManager.cs
+10 -5
@@ -5,15 +5,20 @@ namespace WixToolset.Core.WindowsInstaller.Bind
5 using System;
6 using System.Collections.Generic;
7 using System.IO;
8 + using System.Runtime.CompilerServices;
9 using WixToolset.Extensibility;
10 + using WixToolset.Extensibility.Services;
11
12 internal class FileSystemManager
13 {
12 - public FileSystemManager(IEnumerable<IFileSystemExtension> fileSystemExtensions)
14 + public FileSystemManager(IFileSystem fileSystem, IEnumerable<IFileSystemExtension> fileSystemExtensions)
15 {
16 + this.FileSystem = fileSystem;
17 this.Extensions = fileSystemExtensions;
18 }
19
20 + private IFileSystem FileSystem { get; }
21 +
22 private IEnumerable<IFileSystemExtension> Extensions { get; }
23
24 public bool CompareFiles(string firstPath, string secondPath)
@@ -27,18 +32,18 @@ namespace WixToolset.Core.WindowsInstaller.Bind
32 }
33 }
34
30 - return BuiltinCompareFiles(firstPath, secondPath);
35 + return this.BuiltinCompareFiles(firstPath, secondPath);
36 }
37
33 - private static bool BuiltinCompareFiles(string firstPath, string secondPath)
38 + private bool BuiltinCompareFiles(string firstPath, string secondPath)
39 {
40 if (String.Equals(firstPath, secondPath, StringComparison.OrdinalIgnoreCase))
41 {
42 return true;
43 }
44
40 - using (var firstStream = File.OpenRead(firstPath))
41 - using (var secondStream = File.OpenRead(secondPath))
45 + using (var firstStream = this.FileSystem.OpenFile(firstPath, FileMode.Open, FileAccess.Read, FileShare.Read))
46 + using (var secondStream = this.FileSystem.OpenFile(secondPath, FileMode.Open, FileAccess.Read, FileShare.Read))
47 {
48 if (firstStream.Length != secondStream.Length)
49 {
src/wix/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs
+5 -2
@@ -18,10 +18,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
18 {
19 private const string IdtsSubFolder = "_idts";
20
21 - public GenerateDatabaseCommand(IMessaging messaging, IBackendHelper backendHelper, FileSystemManager fileSystemManager, WindowsInstallerData data, string outputPath, TableDefinitionCollection tableDefinitions, string intermediateFolder, bool keepAddedColumns, bool suppressAddingValidationRows, bool useSubdirectory)
21 + public GenerateDatabaseCommand(IMessaging messaging, IBackendHelper backendHelper, IFileSystem fileSystem, FileSystemManager fileSystemManager, WindowsInstallerData data, string outputPath, TableDefinitionCollection tableDefinitions, string intermediateFolder, bool keepAddedColumns, bool suppressAddingValidationRows, bool useSubdirectory)
22 {
23 this.Messaging = messaging;
24 this.BackendHelper = backendHelper;
25 + this.FileSystem = fileSystem;
26 this.FileSystemManager = fileSystemManager;
27 this.Data = data;
28 this.OutputPath = outputPath;
@@ -34,6 +35,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
35
36 private IBackendHelper BackendHelper { get; }
37
38 + private IFileSystem FileSystem { get; }
39 +
40 private FileSystemManager FileSystemManager { get; }
41
42 /// <summary>
@@ -358,7 +361,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
361 var transformFile = Path.Combine(this.IntermediateFolder, String.Concat(subStorage.Name, ".mst"));
362
363 // Bind the transform.
361 - var command = new BindTransformCommand(this.Messaging, this.BackendHelper, this.FileSystemManager, this.IntermediateFolder, subStorage.Data, transformFile, this.TableDefinitions);
364 + var command = new BindTransformCommand(this.Messaging, this.BackendHelper, this.FileSystem, this.FileSystemManager, this.IntermediateFolder, subStorage.Data, transformFile, this.TableDefinitions);
365 command.Execute();
366
367 if (this.Messaging.EncounteredError)
src/wix/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs
+5 -2
@@ -19,9 +19,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
19 /// </summary>
20 internal class UpdateFileFacadesCommand
21 {
22 - public UpdateFileFacadesCommand(IMessaging messaging, IntermediateSection section, IEnumerable<IFileFacade> allFileFacades, IEnumerable<IFileFacade> updateFileFacades, IDictionary<string, string> variableCache, bool overwriteHash)
22 + public UpdateFileFacadesCommand(IMessaging messaging, IFileSystem fileSystem, IntermediateSection section, IEnumerable<IFileFacade> allFileFacades, IEnumerable<IFileFacade> updateFileFacades, IDictionary<string, string> variableCache, bool overwriteHash)
23 {
24 this.Messaging = messaging;
25 + this.FileSystem = fileSystem;
26 this.Section = section;
27 this.AllFileFacades = allFileFacades;
28 this.UpdateFileFacades = updateFileFacades;
@@ -31,6 +32,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
32
33 private IMessaging Messaging { get; }
34
35 + private IFileSystem FileSystem { get; }
36 +
37 private IntermediateSection Section { get; }
38
39 private IEnumerable<IFileFacade> AllFileFacades { get; }
@@ -212,7 +215,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
215 {
216 try
217 {
215 - var assemblyName = AssemblyNameReader.ReadAssembly(facade.SourceLineNumber, fileInfo.FullName, version);
218 + var assemblyName = AssemblyNameReader.ReadAssembly(this.FileSystem, facade.SourceLineNumber, fileInfo.FullName, version);
219
220 this.SetMsiAssemblyName(assemblyNameSymbols, facade, assemblySymbol, "name", assemblyName.Name);
221 this.SetMsiAssemblyName(assemblyNameSymbols, facade, assemblySymbol, "culture", assemblyName.Culture);
src/wix/WixToolset.Core.WindowsInstaller/CommandLine/TransformSubcommand.cs
+6 -3
@@ -21,6 +21,7 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
21 {
22 this.Messaging = serviceProvider.GetService<IMessaging>();
23 this.BackendHelper = serviceProvider.GetService<IBackendHelper>();
24 + this.FileSystem = serviceProvider.GetService<IFileSystem>();
25 this.PathResolver = serviceProvider.GetService<IPathResolver>();
26 this.ExtensionManager = serviceProvider.GetService<IExtensionManager>();
27 }
@@ -29,6 +30,8 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
30
31 private IBackendHelper BackendHelper { get; }
32
33 + private IFileSystem FileSystem { get; }
34 +
35 private IPathResolver PathResolver { get; }
36
37 private IExtensionManager ExtensionManager { get; }
@@ -342,11 +345,11 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
345 else
346 {
347 var fileSystemExtensions = this.ExtensionManager.GetServices<IFileSystemExtension>();
345 - var fileSystemManager = new FileSystemManager(fileSystemExtensions);
348 + var fileSystemManager = new FileSystemManager(this.FileSystem, fileSystemExtensions);
349
350 var tableDefinitions = this.GetTableDefinitions();
351
349 - var bindCommand = new BindTransformCommand(this.Messaging, this.BackendHelper, fileSystemManager, this.IntermediateFolder, transform, this.OutputPath, tableDefinitions);
352 + var bindCommand = new BindTransformCommand(this.Messaging, this.BackendHelper, this.FileSystem, fileSystemManager, this.IntermediateFolder, transform, this.OutputPath, tableDefinitions);
353 bindCommand.Execute();
354 }
355 }
@@ -379,7 +382,7 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
382 {
383 if (!DataLoader.TryLoadWindowsInstallerData(path, out var data))
384 {
382 - var unbindCommand = new UnbindDatabaseCommand(this.Messaging, this.BackendHelper, this.PathResolver, path, null, OutputType.Product, this.ExportBasePath, null, this.IntermediateFolder, enableDemodularization: false, skipSummaryInfo: false);
385 + var unbindCommand = new UnbindDatabaseCommand(this.Messaging, this.BackendHelper, this.FileSystem, this.PathResolver, path, null, OutputType.Product, this.ExportBasePath, null, this.IntermediateFolder, enableDemodularization: false, skipSummaryInfo: false);
386 data = unbindCommand.Execute();
387 }
388
src/wix/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs
+8 -6
@@ -19,6 +19,7 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe
19 public InscribeMsiPackageCommand(IServiceProvider serviceProvider, string inputPath, string intermediateFolder, string outputPath)
20 {
21 this.Messaging = serviceProvider.GetService<IMessaging>();
22 + this.FileSystem = serviceProvider.GetService<IFileSystem>();
23 this.WindowsInstallerBackendHelper = serviceProvider.GetService<IWindowsInstallerBackendHelper>();
24 this.TableDefinitions = new TableDefinitionCollection(WindowsInstallerTableDefinitions.All);
25 this.InputPath = inputPath;
@@ -34,6 +35,8 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe
35
36 private IMessaging Messaging { get; }
37
38 + private IFileSystem FileSystem { get; }
39 +
40 private IWindowsInstallerBackendHelper WindowsInstallerBackendHelper { get; }
41
42 private TableDefinitionCollection TableDefinitions { get; }
@@ -48,8 +51,7 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe
51
52 if (!String.Equals(this.InputPath, this.OutputPath, StringComparison.OrdinalIgnoreCase))
53 {
51 - Directory.CreateDirectory(Path.GetDirectoryName(this.OutputPath));
52 - File.Copy(this.InputPath, this.OutputPath, true);
54 + this.FileSystem.CopyFile(this.InputPath, this.OutputPath, allowHardlink: false);
55 }
56
57 var attributes = File.GetAttributes(databasePath);
@@ -96,7 +98,7 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe
98 Directory.CreateDirectory(hashPath);
99 hashPath = Path.Combine(hashPath, hashFileName);
100
99 - using (var fs = File.Create(hashPath))
101 + using (var fs = this.FileSystem.OpenFile(hashPath, FileMode.Create, FileAccess.Write, FileShare.None))
102 {
103 int bytesRead;
104 var buffer = new byte[1024 * 4];
@@ -127,7 +129,7 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe
129 Directory.CreateDirectory(certPath);
130 certPath = Path.Combine(certPath, String.Concat(certificateId, ".cer"));
131
130 - using (var fs = File.Create(certPath))
132 + using (var fs = this.FileSystem.OpenFile(certPath, FileMode.Create, FileAccess.Write, FileShare.None))
133 {
134 int bytesRead;
135 var buffer = new byte[1024 * 4];
@@ -221,9 +223,9 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe
223 var certPath = Path.Combine(this.IntermediateFolder, "MsiDigitalCertificate");
224 Directory.CreateDirectory(certPath);
225 certPath = Path.Combine(certPath, String.Concat(cert2.Thumbprint, ".cer"));
224 - File.Delete(certPath);
226 + this.FileSystem.DeleteFile(certPath, true);
227
226 - using (var writer = new BinaryWriter(File.Open(certPath, FileMode.Create)))
228 + using (var writer = new BinaryWriter(this.FileSystem.OpenFile(certPath, FileMode.Create, FileAccess.Write, FileShare.Read)))
229 {
230 writer.Write(cert2.RawData);
231 writer.Close();
src/wix/WixToolset.Core.WindowsInstaller/MspBackend.cs
+3 -1
@@ -17,6 +17,8 @@ namespace WixToolset.Core.WindowsInstaller
17
18 var backendHelper = context.ServiceProvider.GetService<IBackendHelper>();
19
20 + var fileSystem = context.ServiceProvider.GetService<IFileSystem>();
21 +
22 var pathResolver = context.ServiceProvider.GetService<IPathResolver>();
23
24 var fileResolver = context.ServiceProvider.GetService<IFileResolver>();
@@ -36,7 +38,7 @@ namespace WixToolset.Core.WindowsInstaller
38 IEnumerable<PatchTransform> patchTransforms;
39 PatchFilterMap patchFilterMap;
40 {
39 - var command = new CreatePatchTransformsCommand(messaging, backendHelper, pathResolver, fileResolver, resolveExtensions, backendExtensions, context.IntermediateRepresentation, context.IntermediateFolder, context.BindPaths);
41 + var command = new CreatePatchTransformsCommand(messaging, backendHelper, fileSystem, pathResolver, fileResolver, resolveExtensions, backendExtensions, context.IntermediateRepresentation, context.IntermediateFolder, context.BindPaths);
42 command.Execute();
43
44 patchTransforms = command.PatchTransforms;
src/wix/WixToolset.Core.WindowsInstaller/Unbind/ExtractCabinetsCommand.cs
+6 -2
@@ -12,11 +12,13 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
12 using WixToolset.Data;
13 using WixToolset.Data.WindowsInstaller;
14 using WixToolset.Data.WindowsInstaller.Rows;
15 + using WixToolset.Extensibility.Services;
16
17 internal class ExtractCabinetsCommand
18 {
18 - public ExtractCabinetsCommand(WindowsInstallerData output, Database database, string inputFilePath, string exportBasePath, string intermediateFolder, bool treatOutputAsModule = false)
19 + public ExtractCabinetsCommand(IFileSystem fileSystem, WindowsInstallerData output, Database database, string inputFilePath, string exportBasePath, string intermediateFolder, bool treatOutputAsModule = false)
20 {
21 + this.FileSystem = fileSystem;
22 this.Output = output;
23 this.Database = database;
24 this.InputFilePath = inputFilePath;
@@ -27,6 +29,8 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
29
30 public Dictionary<string, MediaRow> ExtractedFileIdsWithMediaRow { get; private set; }
31
32 + private IFileSystem FileSystem { get; }
33 +
34 private WindowsInstallerData Output { get; }
35
36 private Database Database { get; }
@@ -100,7 +104,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
104 // ensure the parent directory exists
105 Directory.CreateDirectory(Path.GetDirectoryName(cabinetPath));
106
103 - using (var fs = File.Create(cabinetPath))
107 + using (var fs = this.FileSystem.OpenFile(cabinetPath, FileMode.Create, FileAccess.Write, FileShare.None))
108 {
109 int bytesRead;
110 var buffer = new byte[4096];
src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs
+8 -5
@@ -21,10 +21,11 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
21 {
22 private static readonly Regex Modularization = new Regex(@"\.[0-9A-Fa-f]{8}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{4}_[0-9A-Fa-f]{12}");
23
24 - public UnbindDatabaseCommand(IMessaging messaging, IBackendHelper backendHelper, IPathResolver pathResolver, string databasePath, Database database, OutputType outputType, string exportBasePath, string extractFilesFolder, string intermediateFolder, bool enableDemodularization, bool skipSummaryInfo)
24 + public UnbindDatabaseCommand(IMessaging messaging, IBackendHelper backendHelper, IFileSystem fileSystem, IPathResolver pathResolver, string databasePath, Database database, OutputType outputType, string exportBasePath, string extractFilesFolder, string intermediateFolder, bool enableDemodularization, bool skipSummaryInfo)
25 {
26 this.Messaging = messaging;
27 this.BackendHelper = backendHelper;
28 + this.FileSystem = fileSystem;
29 this.PathResolver = pathResolver;
30 this.DatabasePath = databasePath;
31 this.Database = database;
@@ -38,9 +39,11 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
39 this.TableDefinitions = new TableDefinitionCollection(WindowsInstallerTableDefinitions.All);
40 }
41
41 - public IMessaging Messaging { get; }
42 + private IMessaging Messaging { get; }
43
43 - public IBackendHelper BackendHelper { get; }
44 + private IBackendHelper BackendHelper { get; }
45 +
46 + private IFileSystem FileSystem { get; }
47
48 private IPathResolver PathResolver { get; }
49
@@ -203,7 +206,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
206
207 Directory.CreateDirectory(Path.Combine(this.ExportBasePath, tableName));
208
206 - using (var fs = File.Create(source))
209 + using (var fs = this.FileSystem.OpenFile(source, FileMode.Create, FileAccess.Write, FileShare.None))
210 {
211 int bytesRead;
212 var buffer = new byte[4096];
@@ -531,7 +534,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
534
535 if (!String.IsNullOrEmpty(this.ExtractFilesFolder))
536 {
534 - var extractCommand = new ExtractCabinetsCommand(output, this.Database, this.DatabasePath, this.ExtractFilesFolder, this.IntermediateFolder);
537 + var extractCommand = new ExtractCabinetsCommand(this.FileSystem, output, this.Database, this.DatabasePath, this.ExtractFilesFolder, this.IntermediateFolder);
538 extractCommand.Execute();
539
540 extractedFileIds = new HashSet<string>(extractCommand.ExtractedFileIdsWithMediaRow.Keys, StringComparer.OrdinalIgnoreCase);
src/wix/WixToolset.Core.WindowsInstaller/Unbind/UnbindTransformCommand.cs
+8 -5
@@ -16,10 +16,11 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
16
17 internal class UnbindTransformCommand
18 {
19 - public UnbindTransformCommand(IMessaging messaging, IBackendHelper backendHelper, IPathResolver pathResolver, FileSystemManager fileSystemManager, string transformFile, string exportBasePath, string intermediateFolder)
19 + public UnbindTransformCommand(IMessaging messaging, IBackendHelper backendHelper, IFileSystem fileSystem, IPathResolver pathResolver, FileSystemManager fileSystemManager, string transformFile, string exportBasePath, string intermediateFolder)
20 {
21 this.Messaging = messaging;
22 this.BackendHelper = backendHelper;
23 + this.FileSystem = fileSystem;
24 this.PathResolver = pathResolver;
25 this.FileSystemManager = fileSystemManager;
26 this.TransformFile = transformFile;
@@ -33,6 +34,8 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
34
35 private IBackendHelper BackendHelper { get; }
36
37 + private IFileSystem FileSystem { get; }
38 +
39 private IPathResolver PathResolver { get; }
40
41 private FileSystemManager FileSystemManager { get; }
@@ -116,7 +119,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
119 using (var msiDatabase = this.ApplyTransformToSchemaDatabase(schemaDatabasePath, TransformErrorConditions.All | TransformErrorConditions.ViewTransform))
120 {
121 // unbind the database
119 - var unbindCommand = new UnbindDatabaseCommand(this.Messaging, this.BackendHelper, this.PathResolver, schemaDatabasePath, msiDatabase, OutputType.Product, null, null, this.IntermediateFolder, enableDemodularization: false, skipSummaryInfo: true);
122 + var unbindCommand = new UnbindDatabaseCommand(this.Messaging, this.BackendHelper, this.FileSystem, this.PathResolver, schemaDatabasePath, msiDatabase, OutputType.Product, null, null, this.IntermediateFolder, enableDemodularization: false, skipSummaryInfo: true);
123 var transformViewOutput = unbindCommand.Execute();
124
125 return transformViewOutput.Tables["_TransformView"];
@@ -177,7 +180,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
180 {
181
182 // unbind the database
180 - var unbindCommand = new UnbindDatabaseCommand(this.Messaging, this.BackendHelper, this.PathResolver, schemaDatabasePath, database, OutputType.Product, this.ExportBasePath, null, this.IntermediateFolder, enableDemodularization: false, skipSummaryInfo: true);
183 + var unbindCommand = new UnbindDatabaseCommand(this.Messaging, this.BackendHelper, this.FileSystem, this.PathResolver, schemaDatabasePath, database, OutputType.Product, this.ExportBasePath, null, this.IntermediateFolder, enableDemodularization: false, skipSummaryInfo: true);
184 output = unbindCommand.Execute();
185 }
186
@@ -324,7 +327,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
327 if (null == this.EmptyFile)
328 {
329 this.EmptyFile = Path.Combine(this.IntermediateFolder, ".empty");
327 - using (var fileStream = File.Create(this.EmptyFile))
330 + using (var fileStream = this.FileSystem.OpenFile(this.EmptyFile, FileMode.Create, FileAccess.Write, FileShare.None))
331 {
332 }
333 }
@@ -343,7 +346,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
346
347 private void GenerateDatabase(WindowsInstallerData data)
348 {
346 - var command = new GenerateDatabaseCommand(this.Messaging, this.BackendHelper, this.FileSystemManager, data, data.SourceLineNumbers.FileName, this.TableDefinitions, this.IntermediateFolder, keepAddedColumns: true, suppressAddingValidationRows: true, useSubdirectory: false);
349 + var command = new GenerateDatabaseCommand(this.Messaging, this.BackendHelper, this.FileSystem, this.FileSystemManager, data, data.SourceLineNumbers.FileName, this.TableDefinitions, this.IntermediateFolder, keepAddedColumns: true, suppressAddingValidationRows: true, useSubdirectory: false);
350 command.Execute();
351 }
352
src/wix/WixToolset.Core.WindowsInstaller/Validate/ValidateDatabaseCommand.cs
+1 -7
@@ -34,9 +34,6 @@ namespace WixToolset.Core.WindowsInstaller.Validate
34
35 public IEnumerable<ITrackedFile> TrackedFiles { get; private set; }
36
37 - /// <summary>
38 - /// Encountered error implementation for <see cref="IWindowsInstallerValidatorCallback"/>.
39 - /// </summary>
37 public bool EncounteredError => this.Messaging.EncounteredError;
38
39 private IMessaging Messaging { get; }
@@ -84,10 +81,7 @@ namespace WixToolset.Core.WindowsInstaller.Validate
81 }
82 finally
83 {
87 - if (File.Exists(workingDatabasePath))
88 - {
89 - File.Delete(workingDatabasePath);
90 - }
84 + this.FileSystem.DeleteFile(workingDatabasePath);
85 }
86
87 stopwatch.Stop();
src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerDecompiler.cs
+9 -8
@@ -3,7 +3,6 @@
3 namespace WixToolset.Core.WindowsInstaller
4 {
5 using System;
6 - using System.Collections.Generic;
6 using System.IO;
7 using System.Linq;
8 using WixToolset.Core.WindowsInstaller.Bind;
@@ -74,25 +73,27 @@ namespace WixToolset.Core.WindowsInstaller
73
74 var backendHelper = context.ServiceProvider.GetService<IWindowsInstallerBackendHelper>();
75
76 + var fileSystem = context.ServiceProvider.GetService<IFileSystem>();
77 +
78 var pathResolver = context.ServiceProvider.GetService<IPathResolver>();
79
80 if (context.DecompileType == OutputType.Transform)
81 {
81 - return this.DecompileTransform(context, backendHelper, pathResolver);
82 + return this.DecompileTransform(context, backendHelper, fileSystem, pathResolver);
83 }
84 else
85 {
85 - return this.DecompileDatabase(context, backendHelper, pathResolver);
86 + return this.DecompileDatabase(context, backendHelper, fileSystem, pathResolver);
87 }
88 }
89
89 - private IWindowsInstallerDecompileResult DecompileDatabase(IWindowsInstallerDecompileContext context, IWindowsInstallerBackendHelper backendHelper, IPathResolver pathResolver)
90 + private IWindowsInstallerDecompileResult DecompileDatabase(IWindowsInstallerDecompileContext context, IWindowsInstallerBackendHelper backendHelper, IFileSystem fileSystem, IPathResolver pathResolver)
91 {
92 var extractFilesFolder = context.SuppressExtractCabinets || (String.IsNullOrEmpty(context.CabinetExtractFolder) && String.IsNullOrEmpty(context.ExtractFolder)) ? null :
93 String.IsNullOrEmpty(context.CabinetExtractFolder) ? Path.Combine(context.ExtractFolder, "File") : context.CabinetExtractFolder;
94
95 var outputType = context.TreatProductAsModule ? OutputType.Module : context.DecompileType;
95 - var unbindCommand = new UnbindDatabaseCommand(this.Messaging, backendHelper, pathResolver, context.DecompilePath, null, outputType, context.ExtractFolder, extractFilesFolder, context.IntermediateFolder, enableDemodularization: true, skipSummaryInfo: false);
96 + var unbindCommand = new UnbindDatabaseCommand(this.Messaging, backendHelper, fileSystem, pathResolver, context.DecompilePath, null, outputType, context.ExtractFolder, extractFilesFolder, context.IntermediateFolder, enableDemodularization: true, skipSummaryInfo: false);
97 var output = unbindCommand.Execute();
98 var extractedFilePaths = unbindCommand.ExportedFiles;
99
@@ -108,13 +109,13 @@ namespace WixToolset.Core.WindowsInstaller
109 return result;
110 }
111
111 - private IWindowsInstallerDecompileResult DecompileTransform(IWindowsInstallerDecompileContext context, IWindowsInstallerBackendHelper backendHelper, IPathResolver pathResolver)
112 + private IWindowsInstallerDecompileResult DecompileTransform(IWindowsInstallerDecompileContext context, IWindowsInstallerBackendHelper backendHelper, IFileSystem fileSystem, IPathResolver pathResolver)
113 {
114 var fileSystemExtensions = this.ExtensionManager.GetServices<IFileSystemExtension>();
115
115 - var fileSystemManager = new FileSystemManager(fileSystemExtensions);
116 + var fileSystemManager = new FileSystemManager(fileSystem, fileSystemExtensions);
117
117 - var unbindCommand = new UnbindTransformCommand(this.Messaging, backendHelper, pathResolver, fileSystemManager, context.DecompilePath, context.ExtractFolder, context.IntermediateFolder);
118 + var unbindCommand = new UnbindTransformCommand(this.Messaging, backendHelper, fileSystem, pathResolver, fileSystemManager, context.DecompilePath, context.ExtractFolder, context.IntermediateFolder);
119 var output = unbindCommand.Execute();
120
121 var result = context.ServiceProvider.GetService<IWindowsInstallerDecompileResult>();
src/wix/WixToolset.Core/Common.cs
-38
@@ -361,44 +361,6 @@ namespace WixToolset.Core
361 return false;
362 }
363
364 - /// <summary>
365 - /// Recursively loops through a directory, changing an attribute on all of the underlying files.
366 - /// An example is to add/remove the ReadOnly flag from each file.
367 - /// </summary>
368 - /// <param name="path">The directory path to start deleting from.</param>
369 - /// <param name="fileAttribute">The FileAttribute to change on each file.</param>
370 - /// <param name="messageHandler">The message handler.</param>
371 - /// <param name="markAttribute">If true, add the attribute to each file. If false, remove it.</param>
372 - private static void RecursiveFileAttributes(string path, FileAttributes fileAttribute, bool markAttribute, IMessaging messageHandler)
373 - {
374 - foreach (var subDirectory in Directory.GetDirectories(path))
375 - {
376 - RecursiveFileAttributes(subDirectory, fileAttribute, markAttribute, messageHandler);
377 - }
378 -
379 - foreach (var filePath in Directory.GetFiles(path))
380 - {
381 - var attributes = File.GetAttributes(filePath);
382 - if (markAttribute)
383 - {
384 - attributes = attributes | fileAttribute; // add to list of attributes
385 - }
386 - else if (fileAttribute == (attributes & fileAttribute)) // if attribute set
387 - {
388 - attributes = attributes ^ fileAttribute; // remove from list of attributes
389 - }
390 -
391 - try
392 - {
393 - File.SetAttributes(filePath, attributes);
394 - }
395 - catch (UnauthorizedAccessException)
396 - {
397 - messageHandler.Write(WarningMessages.AccessDeniedForSettingAttributes(null, filePath));
398 - }
399 - }
400 - }
401 -
364 /// <summary>
365 /// Takes an id, and demodularizes it (if possible).
366 /// </summary>
src/wix/WixToolset.Core/ExtensibilityServices/FileSystem.cs
+21 -1
@@ -3,6 +3,7 @@
3 namespace WixToolset.Core.ExtensibilityServices
4 {
5 using System;
6 + using System.ComponentModel;
7 using System.IO;
8 using System.Runtime.InteropServices;
9 using System.Threading;
@@ -50,6 +51,25 @@ namespace WixToolset.Core.ExtensibilityServices
51 this.ExecuteWithRetries(() => File.Move(source, destination));
52 }
53
54 + public FileStream OpenFile(string path, FileMode mode, FileAccess access, FileShare share)
55 + {
56 + const int maxRetries = 4;
57 +
58 + for (var attempt = 1; attempt <= maxRetries; ++attempt)
59 + {
60 + try
61 + {
62 + return File.Open(path, mode, access, share);
63 + }
64 + catch (Exception e) when (attempt < maxRetries && (e is IOException || e is SystemException || e is Win32Exception))
65 + {
66 + Thread.Sleep(250);
67 + }
68 + }
69 +
70 + throw new InvalidOperationException("Cannot reach this code");
71 + }
72 +
73 public void ExecuteWithRetries(Action action, int maxRetries = 4)
74 {
75 for (var attempt = 1; attempt <= maxRetries; ++attempt)
@@ -59,7 +79,7 @@ namespace WixToolset.Core.ExtensibilityServices
79 action();
80 break;
81 }
62 - catch when (attempt < maxRetries)
82 + catch (Exception e) when (attempt < maxRetries && (e is IOException || e is SystemException || e is Win32Exception))
83 {
84 Thread.Sleep(250);
85 }
src/wix/WixToolset.Core/LayoutCreator.cs
+3 -9
@@ -112,15 +112,9 @@ namespace WixToolset.Core
112 // Clean up temp files.
113 foreach (var tempPath in uniqueTempPaths)
114 {
115 - try
116 - {
117 - this.SplitUniqueFolders(intermediateFolder, tempPath, uniqueFolders);
115 + this.SplitUniqueFolders(intermediateFolder, tempPath, uniqueFolders);
116
119 - File.Delete(tempPath);
120 - }
121 - catch // delete is best effort.
122 - {
123 - }
117 + this.FileSystem.DeleteFile(tempPath);
118 }
119
120 // Clean up empty temp folders.
@@ -140,7 +134,7 @@ namespace WixToolset.Core
134 {
135 if (tempPath.StartsWith(intermediateFolder, StringComparison.OrdinalIgnoreCase))
136 {
143 - var folder = Path.GetDirectoryName(tempPath).Substring(intermediateFolder.Length);
137 + var folder = Path.GetDirectoryName(tempPath.Substring(intermediateFolder.Length));
138
139 var parts = folder.Split(new[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries);
140