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