aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core/Binder.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core/Binder.cs')
-rw-r--r--src/WixToolset.Core/Binder.cs461
1 files changed, 65 insertions, 396 deletions
diff --git a/src/WixToolset.Core/Binder.cs b/src/WixToolset.Core/Binder.cs
index 9db27fec..c442c94d 100644
--- a/src/WixToolset.Core/Binder.cs
+++ b/src/WixToolset.Core/Binder.cs
@@ -5,10 +5,8 @@ namespace WixToolset.Core
5 using System; 5 using System;
6 using System.Collections.Generic; 6 using System.Collections.Generic;
7 using System.Diagnostics; 7 using System.Diagnostics;
8 using System.IO;
9 using System.Linq; 8 using System.Linq;
10 using System.Reflection; 9 using System.Reflection;
11 using WixToolset.Core.Bind;
12 using WixToolset.Data; 10 using WixToolset.Data;
13 using WixToolset.Data.Bind; 11 using WixToolset.Data.Bind;
14 using WixToolset.Data.Tuples; 12 using WixToolset.Data.Tuples;
@@ -20,334 +18,110 @@ namespace WixToolset.Core
20 /// </summary> 18 /// </summary>
21 public sealed class Binder 19 public sealed class Binder
22 { 20 {
23 //private BinderCore core; 21 public Binder(IServiceProvider serviceProvider)
24 //private List<IBinderExtension> extensions;
25 //private List<IBinderFileManager> fileManagers;
26
27 public Binder()
28 { 22 {
29 //this.DefaultCompressionLevel = CompressionLevel.High; 23 this.ServiceProvider = serviceProvider;
30
31 //this.BindPaths = new List<BindPath>();
32 //this.TargetBindPaths = new List<BindPath>();
33 //this.UpdatedBindPaths = new List<BindPath>();
34
35 //this.extensions = new List<IBinderExtension>();
36 //this.fileManagers = new List<IBinderFileManager>();
37 //this.inspectorExtensions = new List<InspectorExtension>();
38
39 //this.Ices = new List<string>();
40 //this.SuppressIces = new List<string>();
41 } 24 }
42 25
43 private IBindContext Context { get; set; } 26 public int CabbingThreadCount { get; set; }
44
45 //private TableDefinitionCollection TableDefinitions { get; }
46 27
47 //public IEnumerable<IBackendFactory> BackendFactories { get; set; } 28 public string CabCachePath { get; set; }
48 29
49 //public string ContentsFile { private get; set; } 30 public int Codepage { get; set; }
50 31
51 //public string OutputsFile { private get; set; } 32 public CompressionLevel? DefaultCompressionLevel { get; set; }
52 33
53 //public string BuiltOutputsFile { private get; set; } 34 public IEnumerable<IDelayedField> DelayedFields { get; set; }
54 35
55 //public string WixprojectFile { private get; set; } 36 public IEnumerable<IExpectedExtractFile> ExpectedEmbeddedFiles { get; set; }
56 37
57 /// <summary> 38 public IEnumerable<string> Ices { get; set; }
58 /// Gets the list of bindpaths.
59 /// </summary>
60 //public List<BindPath> BindPaths { get; private set; }
61 39
62 /// <summary> 40 public string IntermediateFolder { get; set; }
63 /// Gets the list of target bindpaths.
64 /// </summary>
65 //public List<BindPath> TargetBindPaths { get; private set; }
66 41
67 /// <summary> 42 public Intermediate IntermediateRepresentation { get; set; }
68 /// Gets the list of updated bindpaths.
69 /// </summary>
70 //public List<BindPath> UpdatedBindPaths { get; private set; }
71 43
72 /// <summary> 44 public string OutputPath { get; set; }
73 /// Gets or sets the option to enable building binary delta patches.
74 /// </summary>
75 /// <value>The option to enable building binary delta patches.</value>
76 public bool DeltaBinaryPatch { get; set; }
77 45
78 /// <summary> 46 public string OutputPdbPath { get; set; }
79 /// Gets or sets the cabinet cache location.
80 /// </summary>
81 public string CabCachePath { get; set; }
82 47
83 /// <summary> 48 public IEnumerable<string> SuppressIces { get; set; }
84 /// Gets or sets the number of threads to use for cabinet creation.
85 /// </summary>
86 /// <value>The number of threads to use for cabinet creation.</value>
87 public int CabbingThreadCount { get; set; }
88 49
89 /// <summary>
90 /// Gets or sets the default compression level to use for cabinets
91 /// that don't have their compression level explicitly set.
92 /// </summary>
93 //public CompressionLevel DefaultCompressionLevel { get; set; }
94
95 /// <summary>
96 /// Gets and sets the location to save the WixPdb.
97 /// </summary>
98 /// <value>The location in which to save the WixPdb. Null if the the WixPdb should not be output.</value>
99 //public string PdbFile { get; set; }
100
101 //public List<string> Ices { get; private set; }
102
103 //public List<string> SuppressIces { get; private set; }
104
105 /// <summary>
106 /// Gets and sets the option to suppress resetting ACLs by the binder.
107 /// </summary>
108 /// <value>The option to suppress resetting ACLs by the binder.</value>
109 public bool SuppressAclReset { get; set; }
110
111 /// <summary>
112 /// Gets and sets the option to suppress creating an image for MSI/MSM.
113 /// </summary>
114 /// <value>The option to suppress creating an image for MSI/MSM.</value>
115 public bool SuppressLayout { get; set; }
116
117 /// <summary>
118 /// Gets and sets the option to suppress MSI/MSM validation.
119 /// </summary>
120 /// <value>The option to suppress MSI/MSM validation.</value>
121 /// <remarks>This must be set before calling Bind.</remarks>
122 public bool SuppressValidation { get; set; } 50 public bool SuppressValidation { get; set; }
123 51
124 /// <summary> 52 public bool DeltaBinaryPatch { get; set; }
125 /// Gets and sets the option to suppress adding _Validation table rows.
126 /// </summary>
127 public bool SuppressAddingValidationRows { get; set; }
128
129 /// <summary>
130 /// Gets or sets the localizer.
131 /// </summary>
132 /// <value>The localizer.</value>
133 public Localizer Localizer { get; set; }
134
135 /// <summary>
136 /// Gets or sets the temporary path for the Binder. If left null, the binder
137 /// will use %TEMP% environment variable.
138 /// </summary>
139 /// <value>Path to temp files.</value>
140 public string TempFilesLocation { get; set; }
141
142 /// <summary>
143 /// Gets or sets the Wix variable resolver.
144 /// </summary>
145 /// <value>The Wix variable resolver.</value>
146 internal WixVariableResolver WixVariableResolver { get; set; }
147
148 public BindResult Bind(IBindContext context)
149 {
150 this.Context = context;
151 53
152 this.WriteBuildInfoTable(this.Context.IntermediateRepresentation, this.Context.OutputPath); 54 public IServiceProvider ServiceProvider { get; }
153 55
154 var bindResult = this.BackendBind(); 56 public BindResult Execute()
155 return bindResult;
156 }
157
158//// private ResolveResult Resolve()
159//// {
160//// var buildingPatch = this.Context.IntermediateRepresentation.Sections.Any(s => s.Type == SectionType.Patch);
161
162//// var filesWithEmbeddedFiles = new ExtractEmbeddedFiles();
163
164//// IEnumerable<DelayedField> delayedFields;
165//// {
166//// var command = new ResolveFieldsCommand();
167//// command.Messaging = this.Context.Messaging;
168//// command.BuildingPatch = buildingPatch;
169//// command.BindVariableResolver = this.Context.WixVariableResolver;
170//// command.BindPaths = this.Context.BindPaths;
171//// command.Extensions = this.Context.Extensions;
172//// command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles;
173//// command.IntermediateFolder = this.Context.IntermediateFolder;
174//// command.Intermediate = this.Context.IntermediateRepresentation;
175//// command.SupportDelayedResolution = true;
176//// command.Execute();
177
178//// delayedFields = command.DelayedFields;
179//// }
180
181////#if REVISIT_FOR_PATCHING
182//// if (this.Context.IntermediateRepresentation.SubStorages != null)
183//// {
184//// foreach (SubStorage transform in this.Context.IntermediateRepresentation.SubStorages)
185//// {
186//// var command = new ResolveFieldsCommand();
187//// command.BuildingPatch = buildingPatch;
188//// command.BindVariableResolver = this.Context.WixVariableResolver;
189//// command.BindPaths = this.Context.BindPaths;
190//// command.Extensions = this.Context.Extensions;
191//// command.FilesWithEmbeddedFiles = filesWithEmbeddedFiles;
192//// command.IntermediateFolder = this.Context.IntermediateFolder;
193//// command.Intermediate = this.Context.IntermediateRepresentation;
194//// command.SupportDelayedResolution = false;
195//// command.Execute();
196//// }
197//// }
198////#endif
199
200//// var expectedEmbeddedFiles = filesWithEmbeddedFiles.GetExpectedEmbeddedFiles();
201
202//// return new ResolveResult
203//// {
204//// ExpectedEmbeddedFiles = expectedEmbeddedFiles,
205//// DelayedFields = delayedFields,
206//// };
207//// }
208
209 private BindResult BackendBind()
210 { 57 {
211 var extensionManager = this.Context.ServiceProvider.GetService<IExtensionManager>(); 58 var context = this.ServiceProvider.GetService<IBindContext>();
59 context.Messaging = this.ServiceProvider.GetService<IMessaging>();
60 context.CabbingThreadCount = this.CabbingThreadCount;
61 context.CabCachePath = this.CabCachePath;
62 context.Codepage = this.Codepage;
63 context.DefaultCompressionLevel = this.DefaultCompressionLevel;
64 context.DelayedFields = this.DelayedFields;
65 context.ExpectedEmbeddedFiles = this.ExpectedEmbeddedFiles;
66 context.Extensions = this.ServiceProvider.GetService<IExtensionManager>().Create<IBinderExtension>();
67 context.Ices = this.Ices;
68 context.IntermediateFolder = this.IntermediateFolder;
69 context.IntermediateRepresentation = this.IntermediateRepresentation;
70 context.OutputPath = this.OutputPath;
71 context.OutputPdbPath = this.OutputPdbPath;
72 context.SuppressIces = this.SuppressIces;
73 context.SuppressValidation = this.SuppressValidation;
74
75
76 // Prebind.
77 //
78 foreach (var extension in context.Extensions)
79 {
80 extension.PreBind(context);
81 }
212 82
213 var backendFactories = extensionManager.Create<IBackendFactory>(); 83 // Bind.
84 //
85 this.WriteBuildInfoTable(context.IntermediateRepresentation, context.OutputPath, context.OutputPdbPath);
214 86
215 var entrySection = this.Context.IntermediateRepresentation.Sections[0]; 87 var bindResult = this.BackendBind(context);
216 88
217 foreach (var factory in backendFactories) 89 if (bindResult != null)
218 { 90 {
219 if (factory.TryCreateBackend(entrySection.Type.ToString(), this.Context.OutputPath, null, out var backend)) 91 // Postbind.
92 //
93 foreach (var extension in context.Extensions)
220 { 94 {
221 var result = backend.Bind(this.Context); 95 extension.PostBind(bindResult);
222 return result;
223 } 96 }
224 } 97 }
225 98
226 // TODO: messaging that a backend could not be found to bind the output type? 99 return bindResult;
227
228 return null;
229 } 100 }
230 101
231 /// <summary> 102 private BindResult BackendBind(IBindContext context)
232 /// Binds an output.
233 /// </summary>
234 /// <param name="output">The output to bind.</param>
235 /// <param name="file">The Windows Installer file to create.</param>
236 /// <remarks>The Binder.DeleteTempFiles method should be called after calling this method.</remarks>
237 /// <returns>true if binding completed successfully; false otherwise</returns>
238#if false
239 public bool Bind(Output output, string file)
240 { 103 {
241 // Ensure the cabinet cache path exists if we are going to use it. 104 var extensionManager = context.ServiceProvider.GetService<IExtensionManager>();
242 if (!String.IsNullOrEmpty(this.CabCachePath))
243 {
244 Directory.CreateDirectory(this.CabCachePath);
245 }
246
247 //var fileManagerCore = new BinderFileManagerCore();
248 //fileManagerCore.CabCachePath = this.CabCachePath;
249 //fileManagerCore.Output = output;
250 //fileManagerCore.TempFilesLocation = this.TempFilesLocation;
251 //fileManagerCore.AddBindPaths(this.BindPaths, BindStage.Normal);
252 //fileManagerCore.AddBindPaths(this.TargetBindPaths, BindStage.Target);
253 //fileManagerCore.AddBindPaths(this.UpdatedBindPaths, BindStage.Updated);
254 //foreach (IBinderFileManager fileManager in this.fileManagers)
255 //{
256 // fileManager.Core = fileManagerCore;
257 //}
258
259 this.core = new BinderCore();
260 this.core.FileManagerCore = fileManagerCore;
261
262 this.WriteBuildInfoTable(output, file);
263
264 // Initialize extensions.
265 foreach (IBinderExtension extension in this.extensions)
266 {
267 extension.Core = this.core;
268
269 extension.Initialize(output);
270 }
271
272 // Gather all the wix variables.
273 //Table wixVariableTable = output.Tables["WixVariable"];
274 //if (null != wixVariableTable)
275 //{
276 // foreach (WixVariableRow wixVariableRow in wixVariableTable.Rows)
277 // {
278 // this.WixVariableResolver.AddVariable(wixVariableRow);
279 // }
280 //}
281
282 //BindContext context = new BindContext();
283 //context.CabbingThreadCount = this.CabbingThreadCount;
284 //context.DefaultCompressionLevel = this.DefaultCompressionLevel;
285 //context.Extensions = this.extensions;
286 //context.FileManagerCore = fileManagerCore;
287 //context.FileManagers = this.fileManagers;
288 //context.Ices = this.Ices;
289 //context.IntermediateFolder = this.TempFilesLocation;
290 //context.IntermediateRepresentation = output;
291 //context.Localizer = this.Localizer;
292 //context.OutputPath = file;
293 //context.OutputPdbPath = this.PdbFile;
294 //context.SuppressIces = this.SuppressIces;
295 //context.SuppressValidation = this.SuppressValidation;
296 //context.WixVariableResolver = this.WixVariableResolver;
297
298 BindResult result = null;
299
300 foreach (var factory in this.BackendFactories)
301 {
302 if (factory.TryCreateBackend(output.Type.ToString(), file, null, out var backend))
303 {
304 result = backend.Bind(context);
305 break;
306 }
307 }
308 105
309 if (result == null) 106 var backendFactories = extensionManager.Create<IBackendFactory>();
310 {
311 // TODO: messaging that a backend could not be found to bind the output type?
312 107
313 return false; 108 var entrySection = context.IntermediateRepresentation.Sections[0];
314 }
315 109
316 // Layout media 110 foreach (var factory in backendFactories)
317 try
318 {
319 this.LayoutMedia(result.FileTransfers);
320 }
321 finally
322 { 111 {
323 if (!String.IsNullOrEmpty(this.ContentsFile) && result.ContentFilePaths != null) 112 if (factory.TryCreateBackend(entrySection.Type.ToString(), context.OutputPath, null, out var backend))
324 {
325 this.CreateContentsFile(this.ContentsFile, result.ContentFilePaths);
326 }
327
328 if (!String.IsNullOrEmpty(this.OutputsFile) && result.FileTransfers != null)
329 { 113 {
330 this.CreateOutputsFile(this.OutputsFile, result.FileTransfers, this.PdbFile); 114 var result = backend.Bind(context);
331 } 115 return result;
332
333 if (!String.IsNullOrEmpty(this.BuiltOutputsFile) && result.FileTransfers != null)
334 {
335 this.CreateBuiltOutputsFile(this.BuiltOutputsFile, result.FileTransfers, this.PdbFile);
336 } 116 }
337 } 117 }
338 118
339 this.core = null; 119 // TODO: messaging that a backend could not be found to bind the output type?
340 120
341 return Messaging.Instance.EncounteredError; 121 return null;
342 } 122 }
343#endif 123
344 124 private void WriteBuildInfoTable(Intermediate output, string outputFile, string outputPdbPath)
345 /// <summary>
346 /// Populates the WixBuildInfo table in an output.
347 /// </summary>
348 /// <param name="output">The output.</param>
349 /// <param name="databaseFile">The output file if OutputFile not set.</param>
350 private void WriteBuildInfoTable(Intermediate output, string outputFile)
351 { 125 {
352 var entrySection = output.Sections.First(s => s.Type != SectionType.Fragment); 126 var entrySection = output.Sections.First(s => s.Type != SectionType.Fragment);
353 127
@@ -358,117 +132,12 @@ namespace WixToolset.Core
358 buildInfoRow.WixVersion = fileVersion.FileVersion; 132 buildInfoRow.WixVersion = fileVersion.FileVersion;
359 buildInfoRow.WixOutputFile = outputFile; 133 buildInfoRow.WixOutputFile = outputFile;
360 134
361 if (!String.IsNullOrEmpty(this.Context.WixprojectFile)) 135 if (!String.IsNullOrEmpty(outputPdbPath))
362 {
363 buildInfoRow.WixProjectFile = this.Context.WixprojectFile;
364 }
365
366 if (!String.IsNullOrEmpty(this.Context.OutputPdbPath))
367 { 136 {
368 buildInfoRow.WixPdbFile = this.Context.OutputPdbPath; 137 buildInfoRow.WixPdbFile = outputPdbPath;
369 } 138 }
370 139
371 entrySection.Tuples.Add(buildInfoRow); 140 entrySection.Tuples.Add(buildInfoRow);
372 } 141 }
373
374#if DELETE_THIS_CODE
375 /// <summary>
376 /// Binds a bundle.
377 /// </summary>
378 /// <param name="bundle">The bundle to bind.</param>
379 /// <param name="bundleFile">The bundle to create.</param>
380 private void BindBundle(Output bundle, string bundleFile, out IEnumerable<FileTransfer> fileTransfers, out IEnumerable<string> contentPaths)
381 {
382 BindBundleCommand command = new BindBundleCommand();
383 command.DefaultCompressionLevel = this.DefaultCompressionLevel;
384 command.Extensions = this.extensions;
385 command.FileManagerCore = this.fileManagerCore;
386 command.FileManagers = this.fileManagers;
387 command.Output = bundle;
388 command.OutputPath = bundleFile;
389 command.PdbFile = this.PdbFile;
390 command.TableDefinitions = this.core.TableDefinitions;
391 command.TempFilesLocation = this.TempFilesLocation;
392 command.WixVariableResolver = this.WixVariableResolver;
393 command.Execute();
394
395 fileTransfers = command.FileTransfers;
396 contentPaths = command.ContentFilePaths;
397 }
398
399 /// <summary>
400 /// Binds a databse.
401 /// </summary>
402 /// <param name="output">The output to bind.</param>
403 /// <param name="databaseFile">The database file to create.</param>
404 private void BindDatabase(Output output, string databaseFile, out IEnumerable<FileTransfer> fileTransfers, out IEnumerable<string> contentPaths)
405 {
406 Validator validator = null;
407
408 // tell the binder about the validator if validation isn't suppressed
409 if (!this.SuppressValidation && (OutputType.Module == output.Type || OutputType.Product == output.Type))
410 {
411 validator = new Validator();
412 validator.TempFilesLocation = Path.Combine(this.TempFilesLocation, "validate");
413
414 // set the default cube file
415 string lightDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
416 string cubePath = (OutputType.Module == output.Type) ? Path.Combine(lightDirectory, "mergemod.cub") : Path.Combine(lightDirectory, "darice.cub");
417 validator.AddCubeFile(cubePath);
418
419 // by default, disable ICEs that have equivalent-or-better checks in WiX
420 this.SuppressIces.Add("ICE08");
421 this.SuppressIces.Add("ICE33");
422 this.SuppressIces.Add("ICE47");
423 this.SuppressIces.Add("ICE66");
424
425 // set the ICEs
426 validator.ICEs = this.Ices.ToArray();
427
428 // set the suppressed ICEs
429 validator.SuppressedICEs = this.SuppressIces.ToArray();
430 }
431
432 BindDatabaseCommand command = new BindDatabaseCommand();
433 command.CabbingThreadCount = this.CabbingThreadCount;
434 command.Codepage = this.Localizer == null ? -1 : this.Localizer.Codepage;
435 command.DefaultCompressionLevel = this.DefaultCompressionLevel;
436 command.Extensions = this.extensions;
437 command.FileManagerCore = this.fileManagerCore;
438 command.FileManagers = this.fileManagers;
439 command.InspectorExtensions = this.inspectorExtensions;
440 command.Localizer = this.Localizer;
441 command.PdbFile = this.PdbFile;
442 command.Output = output;
443 command.OutputPath = databaseFile;
444 command.SuppressAddingValidationRows = this.SuppressAddingValidationRows;
445 command.SuppressLayout = this.SuppressLayout;
446 command.TableDefinitions = this.core.TableDefinitions;
447 command.TempFilesLocation = this.TempFilesLocation;
448 command.Validator = validator;
449 command.WixVariableResolver = this.WixVariableResolver;
450 command.Execute();
451
452 fileTransfers = command.FileTransfers;
453 contentPaths = command.ContentFilePaths;
454 }
455
456 /// <summary>
457 /// Binds a transform.
458 /// </summary>
459 /// <param name="transform">The transform to bind.</param>
460 /// <param name="outputPath">The transform to create.</param>
461 private void BindTransform(Output transform, string outputPath)
462 {
463 BindTransformCommand command = new BindTransformCommand();
464 command.Extensions = this.extensions;
465 command.FileManagers = this.fileManagers;
466 command.TableDefinitions = this.core.TableDefinitions;
467 command.TempFilesLocation = this.TempFilesLocation;
468 command.Transform = transform;
469 command.OutputPath = outputPath;
470 command.Execute();
471 }
472#endif
473 } 142 }
474} 143}