aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2022-07-26 17:20:48 -0700
committerRob Mensching <rob@firegiant.com>2022-08-05 09:22:36 -0700
commit024e03c1ae9d956834b9ccc4d4f91a991507b27c (patch)
treec3a6e2ebe56962aab2ac2d05ad5816a0eb0f3943
parentc832d739c92205b95c95c5deba5cbd5765bb6eca (diff)
downloadwix-024e03c1ae9d956834b9ccc4d4f91a991507b27c.tar.gz
wix-024e03c1ae9d956834b9ccc4d4f91a991507b27c.tar.bz2
wix-024e03c1ae9d956834b9ccc4d4f91a991507b27c.zip
Abstract file system to remove Core to Core.Native dependency
The only dependency Core had on Core.Native was for FileSystem which would be better served as an extensibility service everywhere anyway. This moves FileSystem to Core and exposes it via IFileSystem from Extensibility for use everywhere. Core now carries no native code dependencies.
-rw-r--r--src/api/wix/WixToolset.Extensibility/Services/IFileSystem.cs25
-rw-r--r--src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs5
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/BurnReader.cs23
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/CreateBundleExeCommand.cs8
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/HarvestBundlePackageCommand.cs5
-rw-r--r--src/wix/WixToolset.Core.Burn/CommandLine/ExtractSubcommand.cs9
-rw-r--r--src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleCommand.cs12
-rw-r--r--src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleEngineCommand.cs10
-rw-r--r--src/wix/WixToolset.Core.Native/DateTimeInterop.cs4
-rw-r--r--src/wix/WixToolset.Core.Native/WixToolset.Core.Native.csproj1
-rw-r--r--src/wix/WixToolset.Core.TestPackage/BundleExtractor.cs17
-rw-r--r--src/wix/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs22
-rw-r--r--src/wix/WixToolset.Core.WindowsInstaller/CommandLine/ValidateSubcommand.cs5
-rw-r--r--src/wix/WixToolset.Core.WindowsInstaller/Validate/ValidateDatabaseCommand.cs7
-rw-r--r--src/wix/WixToolset.Core/Bind/TransferFilesCommand.cs25
-rw-r--r--src/wix/WixToolset.Core/ExtensibilityServices/FileSystem.cs (renamed from src/wix/WixToolset.Core.Native/FileSystem.cs)43
-rw-r--r--src/wix/WixToolset.Core/LayoutCreator.cs5
-rw-r--r--src/wix/WixToolset.Core/WixToolset.Core.csproj9
-rw-r--r--src/wix/WixToolset.Core/WixToolsetServiceProvider.cs1
19 files changed, 143 insertions, 93 deletions
diff --git a/src/api/wix/WixToolset.Extensibility/Services/IFileSystem.cs b/src/api/wix/WixToolset.Extensibility/Services/IFileSystem.cs
new file mode 100644
index 00000000..d633c823
--- /dev/null
+++ b/src/api/wix/WixToolset.Extensibility/Services/IFileSystem.cs
@@ -0,0 +1,25 @@
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
3namespace WixToolset.Extensibility.Services
4{
5 /// <summary>
6 /// Abstracts basic file system operations.
7 /// </summary>
8 public interface IFileSystem
9 {
10 /// <summary>
11 /// Copies a file.
12 /// </summary>
13 /// <param name="source">The file to copy.</param>
14 /// <param name="destination">The destination file.</param>
15 /// <param name="allowHardlink">Allow hardlinks.</param>
16 void CopyFile(string source, string destination, bool allowHardlink);
17
18 /// <summary>
19 /// Moves a file.
20 /// </summary>
21 /// <param name="source">The file to move.</param>
22 /// <param name="destination">The destination file.</param>
23 void MoveFile(string source, string destination);
24 }
25}
diff --git a/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs b/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
index 44fb84c7..db4fbf0e 100644
--- a/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
@@ -28,6 +28,7 @@ namespace WixToolset.Core.Burn
28 this.ServiceProvider = context.ServiceProvider; 28 this.ServiceProvider = context.ServiceProvider;
29 29
30 this.Messaging = context.ServiceProvider.GetService<IMessaging>(); 30 this.Messaging = context.ServiceProvider.GetService<IMessaging>();
31 this.FileSystem = context.ServiceProvider.GetService<IFileSystem>();
31 32
32 this.BackendHelper = context.ServiceProvider.GetService<IBackendHelper>(); 33 this.BackendHelper = context.ServiceProvider.GetService<IBackendHelper>();
33 this.InternalBurnBackendHelper = context.ServiceProvider.GetService<IInternalBurnBackendHelper>(); 34 this.InternalBurnBackendHelper = context.ServiceProvider.GetService<IInternalBurnBackendHelper>();
@@ -49,6 +50,8 @@ namespace WixToolset.Core.Burn
49 50
50 private IMessaging Messaging { get; } 51 private IMessaging Messaging { get; }
51 52
53 private IFileSystem FileSystem { get; }
54
52 private IBackendHelper BackendHelper { get; } 55 private IBackendHelper BackendHelper { get; }
53 56
54 private IInternalBurnBackendHelper InternalBurnBackendHelper { get; } 57 private IInternalBurnBackendHelper InternalBurnBackendHelper { get; }
@@ -507,7 +510,7 @@ namespace WixToolset.Core.Burn
507 } 510 }
508 511
509 { 512 {
510 var command = new CreateBundleExeCommand(this.Messaging, this.BackendHelper, this.IntermediateFolder, this.OutputPath, bundleApplicationDllSymbol, bundleSymbol, uxContainer, containers.Values); 513 var command = new CreateBundleExeCommand(this.Messaging, this.FileSystem, this.BackendHelper, this.IntermediateFolder, this.OutputPath, bundleApplicationDllSymbol, bundleSymbol, uxContainer, containers.Values);
511 command.Execute(); 514 command.Execute();
512 515
513 fileTransfers.Add(command.Transfer); 516 fileTransfers.Add(command.Transfer);
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/BurnReader.cs b/src/wix/WixToolset.Core.Burn/Bundles/BurnReader.cs
index e3d0f0af..e87e32c7 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/BurnReader.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/BurnReader.cs
@@ -27,16 +27,19 @@ namespace WixToolset.Core.Burn.Bundles
27 27
28 private BinaryReader binaryReader; 28 private BinaryReader binaryReader;
29 private readonly List<DictionaryEntry> attachedContainerPayloadNames; 29 private readonly List<DictionaryEntry> attachedContainerPayloadNames;
30 private readonly IFileSystem fileSystem;
30 31
31 /// <summary> 32 /// <summary>
32 /// Creates a BurnReader for reading a PE file. 33 /// Creates a BurnReader for reading a PE file.
33 /// </summary> 34 /// </summary>
34 /// <param name="messaging"></param> 35 /// <param name="messaging">Messaging.</param>
36 /// <param name="fileSystem">File system.</param>
35 /// <param name="fileExe">File to read.</param> 37 /// <param name="fileExe">File to read.</param>
36 private BurnReader(IMessaging messaging, string fileExe) 38 private BurnReader(IMessaging messaging, IFileSystem fileSystem, string fileExe)
37 : base(messaging, fileExe) 39 : base(messaging, fileExe)
38 { 40 {
39 this.attachedContainerPayloadNames = new List<DictionaryEntry>(); 41 this.attachedContainerPayloadNames = new List<DictionaryEntry>();
42 this.fileSystem = fileSystem;
40 } 43 }
41 44
42 /// <summary> 45 /// <summary>
@@ -47,13 +50,14 @@ namespace WixToolset.Core.Burn.Bundles
47 /// <summary> 50 /// <summary>
48 /// Opens a Burn reader. 51 /// Opens a Burn reader.
49 /// </summary> 52 /// </summary>
50 /// <param name="messaging"></param> 53 /// <param name="messaging">Messaging.</param>
54 /// <param name="fileSystem">File system.</param>
51 /// <param name="fileExe">Path to file.</param> 55 /// <param name="fileExe">Path to file.</param>
52 /// <returns>Burn reader.</returns> 56 /// <returns>Burn reader.</returns>
53 public static BurnReader Open(IMessaging messaging, string fileExe) 57 public static BurnReader Open(IMessaging messaging, IFileSystem fileSystem, string fileExe)
54 { 58 {
55 var binaryReader = new BinaryReader(File.Open(fileExe, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)); 59 var binaryReader = new BinaryReader(File.Open(fileExe, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete));
56 var reader = new BurnReader(messaging, fileExe) 60 var reader = new BurnReader(messaging, fileSystem, fileExe)
57 { 61 {
58 binaryReader = binaryReader, 62 binaryReader = binaryReader,
59 }; 63 };
@@ -96,8 +100,7 @@ namespace WixToolset.Core.Burn.Bundles
96 var cabinet = new Cabinet(tempCabPath); 100 var cabinet = new Cabinet(tempCabPath);
97 cabinet.Extract(outputDirectory); 101 cabinet.Extract(outputDirectory);
98 102
99 Directory.CreateDirectory(Path.GetDirectoryName(manifestPath)); 103 this.fileSystem.MoveFile(manifestOriginalPath, manifestPath);
100 FileSystem.MoveFile(manifestOriginalPath, manifestPath);
101 104
102 var document = new XmlDocument(); 105 var document = new XmlDocument();
103 document.Load(manifestPath); 106 document.Load(manifestPath);
@@ -114,8 +117,7 @@ namespace WixToolset.Core.Burn.Bundles
114 var sourcePath = Path.Combine(outputDirectory, sourcePathNode.Value); 117 var sourcePath = Path.Combine(outputDirectory, sourcePathNode.Value);
115 var destinationPath = Path.Combine(outputDirectory, filePathNode.Value); 118 var destinationPath = Path.Combine(outputDirectory, filePathNode.Value);
116 119
117 Directory.CreateDirectory(Path.GetDirectoryName(destinationPath)); 120 this.fileSystem.MoveFile(sourcePath, destinationPath);
118 FileSystem.MoveFile(sourcePath, destinationPath);
119 } 121 }
120 122
121 foreach (XmlNode payload in payloads) 123 foreach (XmlNode payload in payloads)
@@ -183,8 +185,7 @@ namespace WixToolset.Core.Burn.Bundles
183 var sourcePath = Path.Combine(outputDirectory, (string)entry.Key); 185 var sourcePath = Path.Combine(outputDirectory, (string)entry.Key);
184 var destinationPath = Path.Combine(outputDirectory, (string)entry.Value); 186 var destinationPath = Path.Combine(outputDirectory, (string)entry.Value);
185 187
186 Directory.CreateDirectory(Path.GetDirectoryName(destinationPath)); 188 this.fileSystem.MoveFile(sourcePath, destinationPath);
187 FileSystem.MoveFile(sourcePath, destinationPath);
188 } 189 }
189 190
190 return true; 191 return true;
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/CreateBundleExeCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/CreateBundleExeCommand.cs
index 67a6cb4a..7fe3c4ec 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/CreateBundleExeCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/CreateBundleExeCommand.cs
@@ -9,7 +9,6 @@ namespace WixToolset.Core.Burn.Bundles
9 using System.Runtime.InteropServices; 9 using System.Runtime.InteropServices;
10 using System.Text; 10 using System.Text;
11 using System.Xml; 11 using System.Xml;
12 using WixToolset.Core.Native;
13 using WixToolset.Data; 12 using WixToolset.Data;
14 using WixToolset.Data.Burn; 13 using WixToolset.Data.Burn;
15 using WixToolset.Data.Symbols; 14 using WixToolset.Data.Symbols;
@@ -19,9 +18,10 @@ namespace WixToolset.Core.Burn.Bundles
19 18
20 internal class CreateBundleExeCommand 19 internal class CreateBundleExeCommand
21 { 20 {
22 public CreateBundleExeCommand(IMessaging messaging, IBackendHelper backendHelper, string intermediateFolder, string outputPath, WixBootstrapperApplicationDllSymbol bootstrapperApplicationDllSymbol, WixBundleSymbol bundleSymbol, WixBundleContainerSymbol uxContainer, IEnumerable<WixBundleContainerSymbol> containers) 21 public CreateBundleExeCommand(IMessaging messaging, IFileSystem fileSystem, IBackendHelper backendHelper, string intermediateFolder, string outputPath, WixBootstrapperApplicationDllSymbol bootstrapperApplicationDllSymbol, WixBundleSymbol bundleSymbol, WixBundleContainerSymbol uxContainer, IEnumerable<WixBundleContainerSymbol> containers)
23 { 22 {
24 this.Messaging = messaging; 23 this.Messaging = messaging;
24 this.FileSystem = fileSystem;
25 this.BackendHelper = backendHelper; 25 this.BackendHelper = backendHelper;
26 this.IntermediateFolder = intermediateFolder; 26 this.IntermediateFolder = intermediateFolder;
27 this.OutputPath = outputPath; 27 this.OutputPath = outputPath;
@@ -35,6 +35,8 @@ namespace WixToolset.Core.Burn.Bundles
35 35
36 private IMessaging Messaging { get; } 36 private IMessaging Messaging { get; }
37 37
38 private IFileSystem FileSystem { get; }
39
38 private IBackendHelper BackendHelper { get; } 40 private IBackendHelper BackendHelper { get; }
39 41
40 private string IntermediateFolder { get; } 42 private string IntermediateFolder { get; }
@@ -68,7 +70,7 @@ namespace WixToolset.Core.Burn.Bundles
68 70
69 this.Transfer = this.BackendHelper.CreateFileTransfer(bundleTempPath, this.OutputPath, true, this.BundleSymbol.SourceLineNumbers); 71 this.Transfer = this.BackendHelper.CreateFileTransfer(bundleTempPath, this.OutputPath, true, this.BundleSymbol.SourceLineNumbers);
70 72
71 FileSystem.CopyFile(stubFile, bundleTempPath, allowHardlink: false); 73 this.FileSystem.CopyFile(stubFile, bundleTempPath, allowHardlink: false);
72 File.SetAttributes(bundleTempPath, FileAttributes.Normal); 74 File.SetAttributes(bundleTempPath, FileAttributes.Normal);
73 75
74 var fourPartVersion = this.GetFourPartVersion(this.BundleSymbol); 76 var fourPartVersion = this.GetFourPartVersion(this.BundleSymbol);
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/HarvestBundlePackageCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/HarvestBundlePackageCommand.cs
index 89e0da98..bc065f2f 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/HarvestBundlePackageCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/HarvestBundlePackageCommand.cs
@@ -18,6 +18,7 @@ namespace WixToolset.Core.Burn.Bundles
18 public HarvestBundlePackageCommand(IServiceProvider serviceProvider, IEnumerable<IBurnBackendBinderExtension> backendExtensions, string intermediateFolder, WixBundlePayloadSymbol payloadSymbol, WixBundleBundlePackagePayloadSymbol packagePayloadSymbol, Dictionary<string, WixBundlePayloadSymbol> packagePayloadsById) 18 public HarvestBundlePackageCommand(IServiceProvider serviceProvider, IEnumerable<IBurnBackendBinderExtension> backendExtensions, string intermediateFolder, WixBundlePayloadSymbol payloadSymbol, WixBundleBundlePackagePayloadSymbol packagePayloadSymbol, Dictionary<string, WixBundlePayloadSymbol> packagePayloadsById)
19 { 19 {
20 this.Messaging = serviceProvider.GetService<IMessaging>(); 20 this.Messaging = serviceProvider.GetService<IMessaging>();
21 this.FileSystem = serviceProvider.GetService<IFileSystem>();
21 this.BackendHelper = serviceProvider.GetService<IBackendHelper>(); 22 this.BackendHelper = serviceProvider.GetService<IBackendHelper>();
22 this.BackendExtensions = backendExtensions; 23 this.BackendExtensions = backendExtensions;
23 this.IntermediateFolder = intermediateFolder; 24 this.IntermediateFolder = intermediateFolder;
@@ -29,6 +30,8 @@ namespace WixToolset.Core.Burn.Bundles
29 30
30 private IMessaging Messaging { get; } 31 private IMessaging Messaging { get; }
31 32
33 private IFileSystem FileSystem { get; }
34
32 private IBackendHelper BackendHelper { get; } 35 private IBackendHelper BackendHelper { get; }
33 36
34 private IEnumerable<IBurnBackendBinderExtension> BackendExtensions { get; } 37 private IEnumerable<IBurnBackendBinderExtension> BackendExtensions { get; }
@@ -66,7 +69,7 @@ namespace WixToolset.Core.Burn.Bundles
66 var sourcePath = this.PackagePayload.SourceFile.Path; 69 var sourcePath = this.PackagePayload.SourceFile.Path;
67 var sourceLineNumbers = this.PackagePayload.SourceLineNumbers; 70 var sourceLineNumbers = this.PackagePayload.SourceLineNumbers;
68 71
69 using (var burnReader = BurnReader.Open(this.Messaging, sourcePath)) 72 using (var burnReader = BurnReader.Open(this.Messaging, this.FileSystem, sourcePath))
70 { 73 {
71 if (burnReader.Invalid) 74 if (burnReader.Invalid)
72 { 75 {
diff --git a/src/wix/WixToolset.Core.Burn/CommandLine/ExtractSubcommand.cs b/src/wix/WixToolset.Core.Burn/CommandLine/ExtractSubcommand.cs
index 605ee045..5d6edc33 100644
--- a/src/wix/WixToolset.Core.Burn/CommandLine/ExtractSubcommand.cs
+++ b/src/wix/WixToolset.Core.Burn/CommandLine/ExtractSubcommand.cs
@@ -7,21 +7,20 @@ namespace WixToolset.Core.Burn.CommandLine
7 using System.Threading; 7 using System.Threading;
8 using System.Threading.Tasks; 8 using System.Threading.Tasks;
9 using WixToolset.Core.Burn.Bundles; 9 using WixToolset.Core.Burn.Bundles;
10 using WixToolset.Core.Burn.Inscribe;
11 using WixToolset.Extensibility.Services; 10 using WixToolset.Extensibility.Services;
12 11
13 internal class ExtractSubcommand : BurnSubcommandBase 12 internal class ExtractSubcommand : BurnSubcommandBase
14 { 13 {
15 public ExtractSubcommand(IServiceProvider serviceProvider) 14 public ExtractSubcommand(IServiceProvider serviceProvider)
16 { 15 {
17 this.ServiceProvider = serviceProvider;
18 this.Messaging = serviceProvider.GetService<IMessaging>(); 16 this.Messaging = serviceProvider.GetService<IMessaging>();
17 this.FileSystem = serviceProvider.GetService<IFileSystem>();
19 } 18 }
20 19
21 private IServiceProvider ServiceProvider { get; }
22
23 private IMessaging Messaging { get; } 20 private IMessaging Messaging { get; }
24 21
22 private IFileSystem FileSystem { get; }
23
25 private string InputPath { get; set; } 24 private string InputPath { get; set; }
26 25
27 private string IntermediateFolder { get; set; } 26 private string IntermediateFolder { get; set; }
@@ -49,7 +48,7 @@ namespace WixToolset.Core.Burn.CommandLine
49 48
50 var uxExtractPath = Path.Combine(this.ExtractPath, "BA"); 49 var uxExtractPath = Path.Combine(this.ExtractPath, "BA");
51 50
52 using (var reader = BurnReader.Open(this.Messaging, this.InputPath)) 51 using (var reader = BurnReader.Open(this.Messaging, this.FileSystem, this.InputPath))
53 { 52 {
54 reader.ExtractUXContainer(uxExtractPath, this.IntermediateFolder); 53 reader.ExtractUXContainer(uxExtractPath, this.IntermediateFolder);
55 54
diff --git a/src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleCommand.cs b/src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleCommand.cs
index 6e071fe7..d68d372c 100644
--- a/src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleCommand.cs
@@ -5,7 +5,6 @@ namespace WixToolset.Core.Burn.Inscribe
5 using System; 5 using System;
6 using System.IO; 6 using System.IO;
7 using WixToolset.Core.Burn.Bundles; 7 using WixToolset.Core.Burn.Bundles;
8 using WixToolset.Core.Native;
9 using WixToolset.Extensibility.Services; 8 using WixToolset.Extensibility.Services;
10 9
11 internal class InscribeBundleCommand 10 internal class InscribeBundleCommand
@@ -13,6 +12,7 @@ namespace WixToolset.Core.Burn.Inscribe
13 public InscribeBundleCommand(IServiceProvider serviceProvider, string inputPath, string signedEngineFile, string outputPath, string intermediateFolder) 12 public InscribeBundleCommand(IServiceProvider serviceProvider, string inputPath, string signedEngineFile, string outputPath, string intermediateFolder)
14 { 13 {
15 this.Messaging = serviceProvider.GetService<IMessaging>(); 14 this.Messaging = serviceProvider.GetService<IMessaging>();
15 this.FileSystem = serviceProvider.GetService<IFileSystem>();
16 this.IntermediateFolder = intermediateFolder; 16 this.IntermediateFolder = intermediateFolder;
17 this.InputFilePath = inputPath; 17 this.InputFilePath = inputPath;
18 this.SignedEngineFile = signedEngineFile; 18 this.SignedEngineFile = signedEngineFile;
@@ -21,6 +21,8 @@ namespace WixToolset.Core.Burn.Inscribe
21 21
22 private IMessaging Messaging { get; } 22 private IMessaging Messaging { get; }
23 23
24 private IFileSystem FileSystem { get; }
25
24 private string IntermediateFolder { get; } 26 private string IntermediateFolder { get; }
25 27
26 private string InputFilePath { get; } 28 private string InputFilePath { get; }
@@ -34,9 +36,9 @@ namespace WixToolset.Core.Burn.Inscribe
34 var inscribed = false; 36 var inscribed = false;
35 var tempFile = Path.Combine(this.IntermediateFolder, "~bundle_engine_signed.exe"); 37 var tempFile = Path.Combine(this.IntermediateFolder, "~bundle_engine_signed.exe");
36 38
37 using (var reader = BurnReader.Open(this.Messaging, this.InputFilePath)) 39 using (var reader = BurnReader.Open(this.Messaging, this.FileSystem, this.InputFilePath))
38 { 40 {
39 FileSystem.CopyFile(this.SignedEngineFile, tempFile, allowHardlink: false); 41 this.FileSystem.CopyFile(this.SignedEngineFile, tempFile, allowHardlink: false);
40 42
41 using (var writer = BurnWriter.Open(this.Messaging, tempFile)) 43 using (var writer = BurnWriter.Open(this.Messaging, tempFile))
42 { 44 {
@@ -44,9 +46,7 @@ namespace WixToolset.Core.Burn.Inscribe
44 } 46 }
45 } 47 }
46 48
47 Directory.CreateDirectory(Path.GetDirectoryName(this.OutputFile)); 49 this.FileSystem.MoveFile(tempFile, this.OutputFile);
48
49 FileSystem.MoveFile(tempFile, this.OutputFile);
50 50
51 return inscribed; 51 return inscribed;
52 } 52 }
diff --git a/src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleEngineCommand.cs b/src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleEngineCommand.cs
index e607a28f..c00788ca 100644
--- a/src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleEngineCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Inscribe/InscribeBundleEngineCommand.cs
@@ -5,7 +5,6 @@ namespace WixToolset.Core.Burn.Inscribe
5 using System; 5 using System;
6 using System.IO; 6 using System.IO;
7 using WixToolset.Core.Burn.Bundles; 7 using WixToolset.Core.Burn.Bundles;
8 using WixToolset.Core.Native;
9 using WixToolset.Extensibility.Services; 8 using WixToolset.Extensibility.Services;
10 9
11 internal class InscribeBundleEngineCommand 10 internal class InscribeBundleEngineCommand
@@ -13,6 +12,7 @@ namespace WixToolset.Core.Burn.Inscribe
13 public InscribeBundleEngineCommand(IServiceProvider serviceProvider, string inputPath, string outputPath, string intermediateFolder) 12 public InscribeBundleEngineCommand(IServiceProvider serviceProvider, string inputPath, string outputPath, string intermediateFolder)
14 { 13 {
15 this.Messaging = serviceProvider.GetService<IMessaging>(); 14 this.Messaging = serviceProvider.GetService<IMessaging>();
15 this.FileSystem = serviceProvider.GetService<IFileSystem>();
16 this.IntermediateFolder = intermediateFolder; 16 this.IntermediateFolder = intermediateFolder;
17 this.InputFilePath = inputPath; 17 this.InputFilePath = inputPath;
18 this.OutputFile = outputPath; 18 this.OutputFile = outputPath;
@@ -20,6 +20,8 @@ namespace WixToolset.Core.Burn.Inscribe
20 20
21 private IMessaging Messaging { get; } 21 private IMessaging Messaging { get; }
22 22
23 private IFileSystem FileSystem { get; }
24
23 private string IntermediateFolder { get; } 25 private string IntermediateFolder { get; }
24 26
25 private string InputFilePath { get; } 27 private string InputFilePath { get; }
@@ -30,7 +32,7 @@ namespace WixToolset.Core.Burn.Inscribe
30 { 32 {
31 var tempFile = Path.Combine(this.IntermediateFolder, "bundle_engine_unsigned.exe"); 33 var tempFile = Path.Combine(this.IntermediateFolder, "bundle_engine_unsigned.exe");
32 34
33 using (var reader = BurnReader.Open(this.Messaging, this.InputFilePath)) 35 using (var reader = BurnReader.Open(this.Messaging, this.FileSystem, this.InputFilePath))
34 using (var writer = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.Read | FileShare.Delete)) 36 using (var writer = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.Read | FileShare.Delete))
35 { 37 {
36 reader.Stream.Seek(0, SeekOrigin.Begin); 38 reader.Stream.Seek(0, SeekOrigin.Begin);
@@ -56,9 +58,7 @@ namespace WixToolset.Core.Burn.Inscribe
56 // TODO: update writer with detached container signatures. 58 // TODO: update writer with detached container signatures.
57 } 59 }
58 60
59 Directory.CreateDirectory(Path.GetDirectoryName(this.OutputFile)); 61 this.FileSystem.MoveFile(tempFile, this.OutputFile);
60
61 FileSystem.MoveFile(tempFile, this.OutputFile);
62 } 62 }
63 } 63 }
64} 64}
diff --git a/src/wix/WixToolset.Core.Native/DateTimeInterop.cs b/src/wix/WixToolset.Core.Native/DateTimeInterop.cs
index d2a0ba2b..9ab4f813 100644
--- a/src/wix/WixToolset.Core.Native/DateTimeInterop.cs
+++ b/src/wix/WixToolset.Core.Native/DateTimeInterop.cs
@@ -20,8 +20,8 @@ namespace WixToolset.Core.Native
20 { 20 {
21 // dateTime.ToLocalTime() does not match FileTimeToLocalFileTime() for some reason. 21 // dateTime.ToLocalTime() does not match FileTimeToLocalFileTime() for some reason.
22 // so we need to call FileTimeToLocalFileTime() from kernel32.dll. 22 // so we need to call FileTimeToLocalFileTime() from kernel32.dll.
23 long filetime = dateTime.ToFileTime(); 23 var filetime = dateTime.ToFileTime();
24 long localTime = 0; 24 var localTime = 0L;
25 FileTimeToLocalFileTime(ref filetime, ref localTime); 25 FileTimeToLocalFileTime(ref filetime, ref localTime);
26 FileTimeToDosDateTime(ref localTime, out cabDate, out cabTime); 26 FileTimeToDosDateTime(ref localTime, out cabDate, out cabTime);
27 } 27 }
diff --git a/src/wix/WixToolset.Core.Native/WixToolset.Core.Native.csproj b/src/wix/WixToolset.Core.Native/WixToolset.Core.Native.csproj
index 6553a276..b5c83fba 100644
--- a/src/wix/WixToolset.Core.Native/WixToolset.Core.Native.csproj
+++ b/src/wix/WixToolset.Core.Native/WixToolset.Core.Native.csproj
@@ -24,6 +24,5 @@
24 24
25 <ItemGroup> 25 <ItemGroup>
26 <PackageReference Include="WixToolset.Data" /> 26 <PackageReference Include="WixToolset.Data" />
27 <PackageReference Include="System.IO.FileSystem.AccessControl" />
28 </ItemGroup> 27 </ItemGroup>
29</Project> 28</Project>
diff --git a/src/wix/WixToolset.Core.TestPackage/BundleExtractor.cs b/src/wix/WixToolset.Core.TestPackage/BundleExtractor.cs
index 3cc98e3a..f8cf49df 100644
--- a/src/wix/WixToolset.Core.TestPackage/BundleExtractor.cs
+++ b/src/wix/WixToolset.Core.TestPackage/BundleExtractor.cs
@@ -39,7 +39,7 @@ namespace WixToolset.Core.TestPackage
39 { 39 {
40 var result = new ExtractBAContainerResult(); 40 var result = new ExtractBAContainerResult();
41 Directory.CreateDirectory(tempFolderPath); 41 Directory.CreateDirectory(tempFolderPath);
42 using (var burnReader = BurnReader.Open(messaging, bundleFilePath)) 42 using (var burnReader = BurnReader.Open(messaging, new TestFileSystem(), bundleFilePath))
43 { 43 {
44 result.Success = burnReader.ExtractUXContainer(baFolderPath, tempFolderPath); 44 result.Success = burnReader.ExtractUXContainer(baFolderPath, tempFolderPath);
45 45
@@ -138,5 +138,20 @@ namespace WixToolset.Core.TestPackage
138 document.Load(Path.Combine(baFolderPath, "manifest.xml")); 138 document.Load(Path.Combine(baFolderPath, "manifest.xml"));
139 return document; 139 return document;
140 } 140 }
141
142 private class TestFileSystem : IFileSystem
143 {
144 public void CopyFile(string source, string destination, bool allowHardlink)
145 {
146 Directory.CreateDirectory(Path.GetDirectoryName(destination));
147 File.Copy(source, destination);
148 }
149
150 public void MoveFile(string source, string destination)
151 {
152 Directory.CreateDirectory(Path.GetDirectoryName(destination));
153 File.Move(source, destination);
154 }
155 }
141 } 156 }
142} 157}
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs
index 7af0ca19..7e6a7de0 100644
--- a/src/wix/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs
+++ b/src/wix/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs
@@ -71,10 +71,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
71 { 71 {
72 merge = MsmInterop.GetMsmMerge(); 72 merge = MsmInterop.GetMsmMerge();
73 73
74 FileSystem.ActionWithRetries(() => merge.OpenLog(logPath)); 74 ActionWithRetries(() => merge.OpenLog(logPath));
75 logOpen = true; 75 logOpen = true;
76 76
77 FileSystem.ActionWithRetries(() => merge.OpenDatabase(this.OutputPath)); 77 ActionWithRetries(() => merge.OpenDatabase(this.OutputPath));
78 databaseOpen = true; 78 databaseOpen = true;
79 79
80 var featureModulesByMergeId = this.Section.Symbols.OfType<WixFeatureModulesSymbol>().GroupBy(t => t.WixMergeRef).ToDictionary(g => g.Key); 80 var featureModulesByMergeId = this.Section.Symbols.OfType<WixFeatureModulesSymbol>().GroupBy(t => t.WixMergeRef).ToDictionary(g => g.Key);
@@ -99,7 +99,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
99 } 99 }
100 100
101 this.Messaging.Write(VerboseMessages.OpeningMergeModule(wixMergeRow.SourceFile, mergeLanguage)); 101 this.Messaging.Write(VerboseMessages.OpeningMergeModule(wixMergeRow.SourceFile, mergeLanguage));
102 FileSystem.ActionWithRetries(() => merge.OpenModule(wixMergeRow.SourceFile, mergeLanguage)); 102 ActionWithRetries(() => merge.OpenModule(wixMergeRow.SourceFile, mergeLanguage));
103 moduleOpen = true; 103 moduleOpen = true;
104 104
105 trackedFiles.Add(this.BackendHelper.TrackFile(wixMergeRow.SourceFile, TrackedFileType.Input, wixMergeRow.SourceLineNumbers)); 105 trackedFiles.Add(this.BackendHelper.TrackFile(wixMergeRow.SourceFile, TrackedFileType.Input, wixMergeRow.SourceLineNumbers));
@@ -340,5 +340,21 @@ namespace WixToolset.Core.WindowsInstaller.Bind
340 340
341 this.TrackedFiles = trackedFiles; 341 this.TrackedFiles = trackedFiles;
342 } 342 }
343
344 internal static void ActionWithRetries(Action action, int maxRetries = 3)
345 {
346 for (var attempt = 1; attempt <= maxRetries; ++attempt)
347 {
348 try
349 {
350 action();
351 break;
352 }
353 catch when (attempt < maxRetries)
354 {
355 Thread.Sleep(250);
356 }
357 }
358 }
343 } 359 }
344} 360}
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/ValidateSubcommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/ValidateSubcommand.cs
index 7d77aa30..eb014086 100644
--- a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/ValidateSubcommand.cs
+++ b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/ValidateSubcommand.cs
@@ -16,10 +16,13 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
16 public ValidateSubcommand(IServiceProvider serviceProvider) 16 public ValidateSubcommand(IServiceProvider serviceProvider)
17 { 17 {
18 this.Messaging = serviceProvider.GetService<IMessaging>(); 18 this.Messaging = serviceProvider.GetService<IMessaging>();
19 this.FileSystem = serviceProvider.GetService<IFileSystem>();
19 } 20 }
20 21
21 private IMessaging Messaging { get; } 22 private IMessaging Messaging { get; }
22 23
24 private IFileSystem FileSystem { get; }
25
23 private string DatabasePath { get; set; } 26 private string DatabasePath { get; set; }
24 27
25 private string WixpdbPath { get; set; } 28 private string WixpdbPath { get; set; }
@@ -76,7 +79,7 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
76 data = WindowsInstallerData.Load(this.WixpdbPath); 79 data = WindowsInstallerData.Load(this.WixpdbPath);
77 } 80 }
78 81
79 var command = new ValidateDatabaseCommand(this.Messaging, this.IntermediateFolder, this.DatabasePath, data, this.CubeFiles, this.Ices, this.SuppressIces); 82 var command = new ValidateDatabaseCommand(this.Messaging, this.FileSystem, this.IntermediateFolder, this.DatabasePath, data, this.CubeFiles, this.Ices, this.SuppressIces);
80 command.Execute(); 83 command.Execute();
81 84
82 return Task.FromResult(this.Messaging.EncounteredError ? 1 : 0); 85 return Task.FromResult(this.Messaging.EncounteredError ? 1 : 0);
diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Validate/ValidateDatabaseCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/Validate/ValidateDatabaseCommand.cs
index fa01a119..06fa6817 100644
--- a/src/wix/WixToolset.Core.WindowsInstaller/Validate/ValidateDatabaseCommand.cs
+++ b/src/wix/WixToolset.Core.WindowsInstaller/Validate/ValidateDatabaseCommand.cs
@@ -18,9 +18,10 @@ namespace WixToolset.Core.WindowsInstaller.Validate
18 // Set of ICEs that have equivalent-or-better checks in WiX. 18 // Set of ICEs that have equivalent-or-better checks in WiX.
19 private static readonly string[] WellKnownSuppressedIces = new[] { "ICE08", "ICE33", "ICE47", "ICE66" }; 19 private static readonly string[] WellKnownSuppressedIces = new[] { "ICE08", "ICE33", "ICE47", "ICE66" };
20 20
21 public ValidateDatabaseCommand(IMessaging messaging, string intermediateFolder, string databasePath, WindowsInstallerData data, IEnumerable<string> cubeFiles, IEnumerable<string> ices, IEnumerable<string> suppressedIces) 21 public ValidateDatabaseCommand(IMessaging messaging, IFileSystem fileSystem, string intermediateFolder, string databasePath, WindowsInstallerData data, IEnumerable<string> cubeFiles, IEnumerable<string> ices, IEnumerable<string> suppressedIces)
22 { 22 {
23 this.Messaging = messaging; 23 this.Messaging = messaging;
24 this.FileSystem = fileSystem;
24 this.Data = data; 25 this.Data = data;
25 this.DatabasePath = databasePath; 26 this.DatabasePath = databasePath;
26 this.CubeFiles = cubeFiles; 27 this.CubeFiles = cubeFiles;
@@ -40,6 +41,8 @@ namespace WixToolset.Core.WindowsInstaller.Validate
40 41
41 private IMessaging Messaging { get; } 42 private IMessaging Messaging { get; }
42 43
44 private IFileSystem FileSystem { get; }
45
43 private WindowsInstallerData Data { get; } 46 private WindowsInstallerData Data { get; }
44 47
45 private string DatabasePath { get; } 48 private string DatabasePath { get; }
@@ -71,7 +74,7 @@ namespace WixToolset.Core.WindowsInstaller.Validate
71 var workingDatabasePath = Path.Combine(this.IntermediateFolder, workingDatabaseFilename); 74 var workingDatabasePath = Path.Combine(this.IntermediateFolder, workingDatabaseFilename);
72 try 75 try
73 { 76 {
74 FileSystem.CopyFile(this.DatabasePath, workingDatabasePath, allowHardlink: false); 77 this.FileSystem.CopyFile(this.DatabasePath, workingDatabasePath, allowHardlink: false);
75 78
76 var attributes = File.GetAttributes(workingDatabasePath); 79 var attributes = File.GetAttributes(workingDatabasePath);
77 File.SetAttributes(workingDatabasePath, attributes & ~FileAttributes.ReadOnly); 80 File.SetAttributes(workingDatabasePath, attributes & ~FileAttributes.ReadOnly);
diff --git a/src/wix/WixToolset.Core/Bind/TransferFilesCommand.cs b/src/wix/WixToolset.Core/Bind/TransferFilesCommand.cs
index b3b74fbc..87c2590f 100644
--- a/src/wix/WixToolset.Core/Bind/TransferFilesCommand.cs
+++ b/src/wix/WixToolset.Core/Bind/TransferFilesCommand.cs
@@ -5,7 +5,7 @@ namespace WixToolset.Core.Bind
5 using System; 5 using System;
6 using System.Collections.Generic; 6 using System.Collections.Generic;
7 using System.IO; 7 using System.IO;
8 using WixToolset.Core.Native; 8 using System.Security.AccessControl;
9 using WixToolset.Data; 9 using WixToolset.Data;
10 using WixToolset.Extensibility; 10 using WixToolset.Extensibility;
11 using WixToolset.Extensibility.Data; 11 using WixToolset.Extensibility.Data;
@@ -13,16 +13,19 @@ namespace WixToolset.Core.Bind
13 13
14 internal class TransferFilesCommand 14 internal class TransferFilesCommand
15 { 15 {
16 public TransferFilesCommand(IMessaging messaging, IEnumerable<ILayoutExtension> extensions, IEnumerable<IFileTransfer> fileTransfers, bool resetAcls) 16 public TransferFilesCommand(IMessaging messaging, IFileSystem fileSystem, IEnumerable<ILayoutExtension> extensions, IEnumerable<IFileTransfer> fileTransfers, bool resetAcls)
17 { 17 {
18 this.Extensions = extensions; 18 this.Extensions = extensions;
19 this.Messaging = messaging; 19 this.Messaging = messaging;
20 this.FileSystem = fileSystem;
20 this.FileTransfers = fileTransfers; 21 this.FileTransfers = fileTransfers;
21 this.ResetAcls = resetAcls; 22 this.ResetAcls = resetAcls;
22 } 23 }
23 24
24 private IMessaging Messaging { get; } 25 private IMessaging Messaging { get; }
25 26
27 private IFileSystem FileSystem { get; }
28
26 private IEnumerable<ILayoutExtension> Extensions { get; } 29 private IEnumerable<ILayoutExtension> Extensions { get; }
27 30
28 private IEnumerable<IFileTransfer> FileTransfers { get; } 31 private IEnumerable<IFileTransfer> FileTransfers { get; }
@@ -158,7 +161,7 @@ namespace WixToolset.Core.Bind
158 { 161 {
159 try 162 try
160 { 163 {
161 FileSystem.ResetAcls(destinationFiles); 164 this.AclReset(destinationFiles);
162 } 165 }
163 catch (Exception e) 166 catch (Exception e)
164 { 167 {
@@ -177,7 +180,7 @@ namespace WixToolset.Core.Bind
177 } 180 }
178 } 181 }
179 182
180 FileSystem.CopyFile(source, destination, allowHardlink: true); 183 this.FileSystem.CopyFile(source, destination, allowHardlink: true);
181 } 184 }
182 185
183 private void MoveFile(string source, string destination) 186 private void MoveFile(string source, string destination)
@@ -190,7 +193,19 @@ namespace WixToolset.Core.Bind
190 } 193 }
191 } 194 }
192 195
193 FileSystem.MoveFile(source, destination); 196 this.FileSystem.MoveFile(source, destination);
197 }
198
199 private void AclReset(IEnumerable<string> files)
200 {
201 var aclReset = new FileSecurity();
202 aclReset.SetAccessRuleProtection(false, false);
203
204 foreach (var file in files)
205 {
206 var fileInfo = new FileInfo(file);
207 ExtensibilityServices.FileSystem.ActionWithRetries(() => fileInfo.SetAccessControl(aclReset));
208 }
194 } 209 }
195 } 210 }
196} 211}
diff --git a/src/wix/WixToolset.Core.Native/FileSystem.cs b/src/wix/WixToolset.Core/ExtensibilityServices/FileSystem.cs
index 3c59c90c..8bda4966 100644
--- a/src/wix/WixToolset.Core.Native/FileSystem.cs
+++ b/src/wix/WixToolset.Core/ExtensibilityServices/FileSystem.cs
@@ -1,26 +1,16 @@
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. 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 2
3namespace WixToolset.Core.Native 3namespace WixToolset.Core.ExtensibilityServices
4{ 4{
5 using System; 5 using System;
6 using System.Collections.Generic;
7 using System.IO; 6 using System.IO;
8 using System.Runtime.InteropServices; 7 using System.Runtime.InteropServices;
9 using System.Security.AccessControl;
10 using System.Threading; 8 using System.Threading;
9 using WixToolset.Extensibility.Services;
11 10
12 /// <summary> 11 internal class FileSystem : IFileSystem
13 /// File system helpers.
14 /// </summary>
15 public static class FileSystem
16 { 12 {
17 /// <summary> 13 public void CopyFile(string source, string destination, bool allowHardlink)
18 /// Copies a file.
19 /// </summary>
20 /// <param name="source">The file to copy.</param>
21 /// <param name="destination">The destination file.</param>
22 /// <param name="allowHardlink">Allow hardlinks.</param>
23 public static void CopyFile(string source, string destination, bool allowHardlink)
24 { 14 {
25 EnsureDirectoryWithoutFile(destination); 15 EnsureDirectoryWithoutFile(destination);
26 16
@@ -41,12 +31,7 @@ namespace WixToolset.Core.Native
41 } 31 }
42 } 32 }
43 33
44 /// <summary> 34 public void MoveFile(string source, string destination)
45 /// Moves a file.
46 /// </summary>
47 /// <param name="source">The file to move.</param>
48 /// <param name="destination">The destination file.</param>
49 public static void MoveFile(string source, string destination)
50 { 35 {
51 EnsureDirectoryWithoutFile(destination); 36 EnsureDirectoryWithoutFile(destination);
52 37
@@ -54,29 +39,13 @@ namespace WixToolset.Core.Native
54 } 39 }
55 40
56 /// <summary> 41 /// <summary>
57 /// Reset the ACLs on a set of files.
58 /// </summary>
59 /// <param name="files">The list of file paths to set ACLs.</param>
60 public static void ResetAcls(IEnumerable<string> files)
61 {
62 var aclReset = new FileSecurity();
63 aclReset.SetAccessRuleProtection(false, false);
64
65 foreach (var file in files)
66 {
67 var fileInfo = new FileInfo(file);
68 ActionWithRetries(() => fileInfo.SetAccessControl(aclReset));
69 }
70 }
71
72 /// <summary>
73 /// Executes an action and retries on any exception up to a few times. Primarily 42 /// Executes an action and retries on any exception up to a few times. Primarily
74 /// intended for use with file system operations that might get interrupted by 43 /// intended for use with file system operations that might get interrupted by
75 /// external systems (usually anti-virus). 44 /// external systems (usually anti-virus).
76 /// </summary> 45 /// </summary>
77 /// <param name="action">Action to execute.</param> 46 /// <param name="action">Action to execute.</param>
78 /// <param name="maxRetries">Maximum retry attempts.</param> 47 /// <param name="maxRetries">Maximum retry attempts.</param>
79 public static void ActionWithRetries(Action action, int maxRetries = 3) 48 internal static void ActionWithRetries(Action action, int maxRetries = 3)
80 { 49 {
81 for (var attempt = 1; attempt <= maxRetries; ++attempt) 50 for (var attempt = 1; attempt <= maxRetries; ++attempt)
82 { 51 {
diff --git a/src/wix/WixToolset.Core/LayoutCreator.cs b/src/wix/WixToolset.Core/LayoutCreator.cs
index 7a143680..3e7ecf3a 100644
--- a/src/wix/WixToolset.Core/LayoutCreator.cs
+++ b/src/wix/WixToolset.Core/LayoutCreator.cs
@@ -21,10 +21,13 @@ namespace WixToolset.Core
21 internal LayoutCreator(IServiceProvider serviceProvider) 21 internal LayoutCreator(IServiceProvider serviceProvider)
22 { 22 {
23 this.Messaging = serviceProvider.GetService<IMessaging>(); 23 this.Messaging = serviceProvider.GetService<IMessaging>();
24 this.FileSystem = serviceProvider.GetService<IFileSystem>();
24 } 25 }
25 26
26 private IMessaging Messaging { get; } 27 private IMessaging Messaging { get; }
27 28
29 private IFileSystem FileSystem { get; }
30
28 public void Layout(ILayoutContext context) 31 public void Layout(ILayoutContext context)
29 { 32 {
30 // Pre-layout. 33 // Pre-layout.
@@ -42,7 +45,7 @@ namespace WixToolset.Core
42 { 45 {
43 this.Messaging.Write(VerboseMessages.LayingOutMedia()); 46 this.Messaging.Write(VerboseMessages.LayingOutMedia());
44 47
45 var command = new TransferFilesCommand(this.Messaging, context.Extensions, context.FileTransfers, context.ResetAcls); 48 var command = new TransferFilesCommand(this.Messaging, this.FileSystem, context.Extensions, context.FileTransfers, context.ResetAcls);
46 command.Execute(); 49 command.Execute();
47 } 50 }
48 51
diff --git a/src/wix/WixToolset.Core/WixToolset.Core.csproj b/src/wix/WixToolset.Core/WixToolset.Core.csproj
index c2551b21..f2ee3a2c 100644
--- a/src/wix/WixToolset.Core/WixToolset.Core.csproj
+++ b/src/wix/WixToolset.Core/WixToolset.Core.csproj
@@ -15,19 +15,12 @@
15 </PropertyGroup> 15 </PropertyGroup>
16 16
17 <ItemGroup> 17 <ItemGroup>
18 <ProjectReference Include="..\WixToolset.Core.Native\WixToolset.Core.Native.csproj" />
19 </ItemGroup>
20
21 <ItemGroup>
22 <PackageReference Include="WixToolset.Data" /> 18 <PackageReference Include="WixToolset.Data" />
23 <PackageReference Include="WixToolset.Extensibility" /> 19 <PackageReference Include="WixToolset.Extensibility" />
24 </ItemGroup> 20 </ItemGroup>
25 21
26 <!--
27 These package references are duplicated in WixToolset.Core.TestPackage.csproj. If
28 you update these here, be sure to update them there.
29 -->
30 <ItemGroup> 22 <ItemGroup>
23 <PackageReference Include="System.IO.FileSystem.AccessControl" />
31 <PackageReference Include="System.Text.Encoding.CodePages" /> 24 <PackageReference Include="System.Text.Encoding.CodePages" />
32 <PackageReference Include="NuGet.Versioning" /> 25 <PackageReference Include="NuGet.Versioning" />
33 </ItemGroup> 26 </ItemGroup>
diff --git a/src/wix/WixToolset.Core/WixToolsetServiceProvider.cs b/src/wix/WixToolset.Core/WixToolsetServiceProvider.cs
index 525b9dd9..fa6b369d 100644
--- a/src/wix/WixToolset.Core/WixToolsetServiceProvider.cs
+++ b/src/wix/WixToolset.Core/WixToolsetServiceProvider.cs
@@ -27,6 +27,7 @@ namespace WixToolset.Core
27 this.AddService((provider, singletons) => AddSingleton<ILayoutServices>(singletons, new LayoutServices(provider))); 27 this.AddService((provider, singletons) => AddSingleton<ILayoutServices>(singletons, new LayoutServices(provider)));
28 this.AddService((provider, singletons) => AddSingleton<IBackendHelper>(singletons, new BackendHelper(provider))); 28 this.AddService((provider, singletons) => AddSingleton<IBackendHelper>(singletons, new BackendHelper(provider)));
29 this.AddService((provider, singletons) => AddSingleton<IPathResolver>(singletons, new PathResolver())); 29 this.AddService((provider, singletons) => AddSingleton<IPathResolver>(singletons, new PathResolver()));
30 this.AddService((provider, singletons) => AddSingleton<IFileSystem>(singletons, new FileSystem()));
30 this.AddService((provider, singletons) => AddSingleton<IWixBranding>(singletons, new WixBranding())); 31 this.AddService((provider, singletons) => AddSingleton<IWixBranding>(singletons, new WixBranding()));
31 32
32 // Transients. 33 // Transients.