aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core.WindowsInstaller
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core.WindowsInstaller')
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs21
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs49
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs15
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs22
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CabinetResolver.cs2
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs16
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs11
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs41
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CreateIdtFileCommand.cs10
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs26
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs18
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs37
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs2
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs43
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/UpdateControlTextCommand.cs11
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs46
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Data/Xsd/actions.xsd73
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Data/Xsd/tables.xsd248
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Differ.cs30
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs14
-rw-r--r--src/WixToolset.Core.WindowsInstaller/MelterCore.cs4
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Msi/WixInvalidIdtException.cs4
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Patch.cs9
-rw-r--r--src/WixToolset.Core.WindowsInstaller/PatchTransform.cs11
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Unbind/ExtractCabinetsCommand.cs2
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs9
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs7
-rw-r--r--src/WixToolset.Core.WindowsInstaller/UnbindContext.cs7
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Unbinder.cs4
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Validator.cs42
-rw-r--r--src/WixToolset.Core.WindowsInstaller/ValidatorExtension.cs36
-rw-r--r--src/WixToolset.Core.WindowsInstaller/WindowsInstallerStandardInternal.cs4
32 files changed, 603 insertions, 271 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs
index 1f2cee74..0f278640 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs
@@ -8,22 +8,25 @@ namespace WixToolset.Core.WindowsInstaller.Bind
8 using System.Linq; 8 using System.Linq;
9 using WixToolset.Core.Bind; 9 using WixToolset.Core.Bind;
10 using WixToolset.Data; 10 using WixToolset.Data;
11 using WixToolset.Data.Rows;
12 using WixToolset.Data.Tuples; 11 using WixToolset.Data.Tuples;
12 using WixToolset.Extensibility.Services;
13 13
14 /// <summary> 14 /// <summary>
15 /// AssignMediaCommand assigns files to cabs based on Media or MediaTemplate rows. 15 /// AssignMediaCommand assigns files to cabs based on Media or MediaTemplate rows.
16 /// </summary> 16 /// </summary>
17 internal class AssignMediaCommand 17 internal class AssignMediaCommand
18 { 18 {
19 public AssignMediaCommand(IntermediateSection section) 19 public AssignMediaCommand(IntermediateSection section, IMessaging messaging)
20 { 20 {
21 this.CabinetNameTemplate = "Cab{0}.cab"; 21 this.CabinetNameTemplate = "Cab{0}.cab";
22 this.Section = section; 22 this.Section = section;
23 this.Messaging = messaging;
23 } 24 }
24 25
25 private IntermediateSection Section { get; } 26 private IntermediateSection Section { get; }
26 27
28 private IMessaging Messaging { get; }
29
27 public IEnumerable<FileFacade> FileFacades { private get; set; } 30 public IEnumerable<FileFacade> FileFacades { private get; set; }
28 31
29 public bool FilesCompressed { private get; set; } 32 public bool FilesCompressed { private get; set; }
@@ -60,7 +63,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
60 // If both tables are authored, it is an error. 63 // If both tables are authored, it is an error.
61 if (mediaTemplateTable.Count > 0 && mediaTable.Count > 1) 64 if (mediaTemplateTable.Count > 0 && mediaTable.Count > 1)
62 { 65 {
63 throw new WixException(WixErrors.MediaTableCollision(null)); 66 throw new WixException(ErrorMessages.MediaTableCollision(null));
64 } 67 }
65 68
66 // When building merge module, all the files go to "#MergeModule.CABinet". 69 // When building merge module, all the files go to "#MergeModule.CABinet".
@@ -144,11 +147,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
144 } 147 }
145 catch (FormatException) 148 catch (FormatException)
146 { 149 {
147 throw new WixException(WixErrors.IllegalEnvironmentVariable("WIX_MUMS", mumsString)); 150 throw new WixException(ErrorMessages.IllegalEnvironmentVariable("WIX_MUMS", mumsString));
148 } 151 }
149 catch (OverflowException) 152 catch (OverflowException)
150 { 153 {
151 throw new WixException(WixErrors.MaximumUncompressedMediaSizeTooLarge(null, maxPreCabSizeInMB)); 154 throw new WixException(ErrorMessages.MaximumUncompressedMediaSizeTooLarge(null, maxPreCabSizeInMB));
152 } 155 }
153 156
154 foreach (FileFacade facade in this.FileFacades) 157 foreach (FileFacade facade in this.FileFacades)
@@ -234,8 +237,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
234 { 237 {
235 if (cabinetMediaRows.TryGetValue(mediaRow.Cabinet, out var existingRow)) 238 if (cabinetMediaRows.TryGetValue(mediaRow.Cabinet, out var existingRow))
236 { 239 {
237 Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName(mediaRow.SourceLineNumbers, mediaRow.Cabinet)); 240 this.Messaging.Write(ErrorMessages.DuplicateCabinetName(mediaRow.SourceLineNumbers, mediaRow.Cabinet));
238 Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName2(existingRow.SourceLineNumbers, existingRow.Cabinet)); 241 this.Messaging.Write(ErrorMessages.DuplicateCabinetName2(existingRow.SourceLineNumbers, existingRow.Cabinet));
239 } 242 }
240 else 243 else
241 { 244 {
@@ -259,7 +262,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
259 { 262 {
260 if (!mediaRows.TryGetValue(facade.WixFile.DiskId, out var mediaRow)) 263 if (!mediaRows.TryGetValue(facade.WixFile.DiskId, out var mediaRow))
261 { 264 {
262 Messaging.Instance.OnMessage(WixErrors.MissingMedia(facade.File.SourceLineNumbers, facade.WixFile.DiskId)); 265 this.Messaging.Write(ErrorMessages.MissingMedia(facade.File.SourceLineNumbers, facade.WixFile.DiskId));
263 continue; 266 continue;
264 } 267 }
265 268
@@ -279,7 +282,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
279 } 282 }
280 else 283 else
281 { 284 {
282 Messaging.Instance.OnMessage(WixErrors.ExpectedMediaCabinet(facade.File.SourceLineNumbers, facade.File.File, facade.WixFile.DiskId)); 285 this.Messaging.Write(ErrorMessages.ExpectedMediaCabinet(facade.File.SourceLineNumbers, facade.File.File, facade.WixFile.DiskId));
283 } 286 }
284 } 287 }
285 } 288 }
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
index 9e30aed2..410e462a 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
@@ -35,6 +35,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
35 this.ExpectedEmbeddedFiles = context.ExpectedEmbeddedFiles; 35 this.ExpectedEmbeddedFiles = context.ExpectedEmbeddedFiles;
36 this.Extensions = context.Extensions; 36 this.Extensions = context.Extensions;
37 this.Intermediate = context.IntermediateRepresentation; 37 this.Intermediate = context.IntermediateRepresentation;
38 this.Messaging = context.Messaging;
38 this.OutputPath = context.OutputPath; 39 this.OutputPath = context.OutputPath;
39 this.PdbFile = context.OutputPdbPath; 40 this.PdbFile = context.OutputPdbPath;
40 this.IntermediateFolder = context.IntermediateFolder; 41 this.IntermediateFolder = context.IntermediateFolder;
@@ -68,6 +69,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
68 69
69 private Intermediate Intermediate { get; } 70 private Intermediate Intermediate { get; }
70 71
72 private IMessaging Messaging { get; }
73
71 private string OutputPath { get; } 74 private string OutputPath { get; }
72 75
73 private bool SuppressAddingValidationRows { get; } 76 private bool SuppressAddingValidationRows { get; }
@@ -160,7 +163,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
160 // Sequence all the actions. 163 // Sequence all the actions.
161 { 164 {
162 var command = new SequenceActionsCommand(section); 165 var command = new SequenceActionsCommand(section);
163 command.Messaging = Messaging.Instance; 166 command.Messaging = this.Messaging;
164 command.Execute(); 167 command.Execute();
165 } 168 }
166 169
@@ -191,12 +194,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
191 ////} 194 ////}
192#endif 195#endif
193 196
194 if (Messaging.Instance.EncounteredError) 197 if (this.Messaging.EncounteredError)
195 { 198 {
196 return; 199 return;
197 } 200 }
198 201
199 Messaging.Instance.OnMessage(WixVerboses.UpdatingFileInformation()); 202 this.Messaging.Write(VerboseMessages.UpdatingFileInformation());
200 203
201 // This must occur after all variables and source paths have been resolved. 204 // This must occur after all variables and source paths have been resolved.
202 List<FileFacade> fileFacades; 205 List<FileFacade> fileFacades;
@@ -215,7 +218,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
215 218
216 // Gather information about files that did not come from merge modules (i.e. rows with a reference to the File table). 219 // Gather information about files that did not come from merge modules (i.e. rows with a reference to the File table).
217 { 220 {
218 var command = new UpdateFileFacadesCommand(section); 221 var command = new UpdateFileFacadesCommand(this.Messaging, section);
219 command.FileFacades = fileFacades; 222 command.FileFacades = fileFacades;
220 command.UpdateFileFacades = fileFacades.Where(f => !f.FromModule); 223 command.UpdateFileFacades = fileFacades.Where(f => !f.FromModule);
221 command.OverwriteHash = true; 224 command.OverwriteHash = true;
@@ -227,13 +230,13 @@ namespace WixToolset.Core.WindowsInstaller.Bind
227 // Now that the variable cache is populated, resolve any delayed fields. 230 // Now that the variable cache is populated, resolve any delayed fields.
228 if (this.DelayedFields.Any()) 231 if (this.DelayedFields.Any())
229 { 232 {
230 var command = new ResolveDelayedFieldsCommand(this.DelayedFields, variableCache); 233 var command = new ResolveDelayedFieldsCommand(this.Messaging, this.DelayedFields, variableCache);
231 command.Execute(); 234 command.Execute();
232 } 235 }
233 236
234 // Set generated component guids. 237 // Set generated component guids.
235 { 238 {
236 var command = new CalculateComponentGuids(section); 239 var command = new CalculateComponentGuids(this.Messaging, section);
237 command.Execute(); 240 command.Execute();
238 } 241 }
239 242
@@ -244,7 +247,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
244 247
245 if (wixMergeTuples.Any()) 248 if (wixMergeTuples.Any())
246 { 249 {
247 var command = new ExtractMergeModuleFilesCommand(section, wixMergeTuples); 250 var command = new ExtractMergeModuleFilesCommand(this.Messaging, section, wixMergeTuples);
248 command.FileFacades = fileFacades; 251 command.FileFacades = fileFacades;
249 command.OutputInstallerVersion = installerVersion; 252 command.OutputInstallerVersion = installerVersion;
250 command.SuppressLayout = this.SuppressLayout; 253 command.SuppressLayout = this.SuppressLayout;
@@ -265,7 +268,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
265#endif 268#endif
266 269
267 // stop processing if an error previously occurred 270 // stop processing if an error previously occurred
268 if (Messaging.Instance.EncounteredError) 271 if (this.Messaging.EncounteredError)
269 { 272 {
270 return; 273 return;
271 } 274 }
@@ -280,7 +283,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
280 Dictionary<MediaTuple, IEnumerable<FileFacade>> filesByCabinetMedia; 283 Dictionary<MediaTuple, IEnumerable<FileFacade>> filesByCabinetMedia;
281 IEnumerable<FileFacade> uncompressedFiles; 284 IEnumerable<FileFacade> uncompressedFiles;
282 { 285 {
283 var command = new AssignMediaCommand(section); 286 var command = new AssignMediaCommand(section, this.Messaging);
284 command.FileFacades = fileFacades; 287 command.FileFacades = fileFacades;
285 command.FilesCompressed = compressed; 288 command.FilesCompressed = compressed;
286 command.Execute(); 289 command.Execute();
@@ -291,7 +294,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
291 } 294 }
292 295
293 // stop processing if an error previously occurred 296 // stop processing if an error previously occurred
294 if (Messaging.Instance.EncounteredError) 297 if (this.Messaging.EncounteredError)
295 { 298 {
296 return; 299 return;
297 } 300 }
@@ -355,7 +358,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
355#endif 358#endif
356 359
357 // Stop processing if an error previously occurred. 360 // Stop processing if an error previously occurred.
358 if (Messaging.Instance.EncounteredError) 361 if (this.Messaging.EncounteredError)
359 { 362 {
360 return; 363 return;
361 } 364 }
@@ -374,13 +377,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
374 string layoutDirectory = Path.GetDirectoryName(this.OutputPath); 377 string layoutDirectory = Path.GetDirectoryName(this.OutputPath);
375 if (!this.SuppressLayout || OutputType.Module == output.Type) 378 if (!this.SuppressLayout || OutputType.Module == output.Type)
376 { 379 {
377 Messaging.Instance.OnMessage(WixVerboses.CreatingCabinetFiles()); 380 this.Messaging.Write(VerboseMessages.CreatingCabinetFiles());
378 381
379 var command = new CreateCabinetsCommand(); 382 var command = new CreateCabinetsCommand();
380 command.CabbingThreadCount = this.CabbingThreadCount; 383 command.CabbingThreadCount = this.CabbingThreadCount;
381 command.CabCachePath = this.CabCachePath; 384 command.CabCachePath = this.CabCachePath;
382 command.DefaultCompressionLevel = this.DefaultCompressionLevel; 385 command.DefaultCompressionLevel = this.DefaultCompressionLevel;
383 command.Output = output; 386 command.Output = output;
387 command.Messaging = this.Messaging;
384 command.BackendExtensions = this.BackendExtensions; 388 command.BackendExtensions = this.BackendExtensions;
385 command.LayoutDirectory = layoutDirectory; 389 command.LayoutDirectory = layoutDirectory;
386 command.Compressed = compressed; 390 command.Compressed = compressed;
@@ -435,13 +439,13 @@ namespace WixToolset.Core.WindowsInstaller.Bind
435 this.ValidateComponentGuids(output); 439 this.ValidateComponentGuids(output);
436 440
437 // stop processing if an error previously occurred 441 // stop processing if an error previously occurred
438 if (Messaging.Instance.EncounteredError) 442 if (this.Messaging.EncounteredError)
439 { 443 {
440 return; 444 return;
441 } 445 }
442 446
443 // Generate database file. 447 // Generate database file.
444 Messaging.Instance.OnMessage(WixVerboses.GeneratingDatabase()); 448 this.Messaging.Write(VerboseMessages.GeneratingDatabase());
445 string tempDatabaseFile = Path.Combine(this.IntermediateFolder, Path.GetFileName(this.OutputPath)); 449 string tempDatabaseFile = Path.Combine(this.IntermediateFolder, Path.GetFileName(this.OutputPath));
446 this.GenerateDatabase(output, tempDatabaseFile, false, false); 450 this.GenerateDatabase(output, tempDatabaseFile, false, false);
447 451
@@ -452,7 +456,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
452 } 456 }
453 457
454 // Stop processing if an error previously occurred. 458 // Stop processing if an error previously occurred.
455 if (Messaging.Instance.EncounteredError) 459 if (this.Messaging.EncounteredError)
456 { 460 {
457 return; 461 return;
458 } 462 }
@@ -468,7 +472,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
468 // Merge modules. 472 // Merge modules.
469 if (OutputType.Product == output.Type) 473 if (OutputType.Product == output.Type)
470 { 474 {
471 Messaging.Instance.OnMessage(WixVerboses.MergingModules()); 475 this.Messaging.Write(VerboseMessages.MergingModules());
472 476
473 var command = new MergeModulesCommand(); 477 var command = new MergeModulesCommand();
474 command.FileFacades = fileFacades; 478 command.FileFacades = fileFacades;
@@ -478,7 +482,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
478 command.Execute(); 482 command.Execute();
479 } 483 }
480 484
481 if (Messaging.Instance.EncounteredError) 485 if (this.Messaging.EncounteredError)
482 { 486 {
483 return; 487 return;
484 } 488 }
@@ -492,12 +496,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
492 // set the output file for source line information 496 // set the output file for source line information
493 this.Validator.Output = this.Output; 497 this.Validator.Output = this.Output;
494 498
495 Messaging.Instance.OnMessage(WixVerboses.ValidatingDatabase()); 499 Messaging.Instance.Write(WixVerboses.ValidatingDatabase());
496 500
497 this.Validator.Validate(tempDatabaseFile); 501 this.Validator.Validate(tempDatabaseFile);
498 502
499 stopwatch.Stop(); 503 stopwatch.Stop();
500 Messaging.Instance.OnMessage(WixVerboses.ValidatedDatabase(stopwatch.ElapsedMilliseconds)); 504 Messaging.Instance.Write(WixVerboses.ValidatedDatabase(stopwatch.ElapsedMilliseconds));
501 505
502 // Stop processing if an error occurred. 506 // Stop processing if an error occurred.
503 if (Messaging.Instance.EncounteredError) 507 if (Messaging.Instance.EncounteredError)
@@ -508,7 +512,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
508#endif 512#endif
509 513
510 // Process uncompressed files. 514 // Process uncompressed files.
511 if (!Messaging.Instance.EncounteredError && !this.SuppressLayout && uncompressedFiles.Any()) 515 if (!this.Messaging.EncounteredError && !this.SuppressLayout && uncompressedFiles.Any())
512 { 516 {
513 var command = new ProcessUncompressedFilesCommand(section); 517 var command = new ProcessUncompressedFilesCommand(section);
514 command.Compressed = compressed; 518 command.Compressed = compressed;
@@ -908,11 +912,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
908 912
909 if (allComponentsHaveConditions) 913 if (allComponentsHaveConditions)
910 { 914 {
911 Messaging.Instance.OnMessage(WixWarnings.DuplicateComponentGuidsMustHaveMutuallyExclusiveConditions(row.SourceLineNumbers, row.Component, row.Guid)); 915 this.Messaging.Write(WarningMessages.DuplicateComponentGuidsMustHaveMutuallyExclusiveConditions(row.SourceLineNumbers, row.Component, row.Guid));
912 } 916 }
913 else 917 else
914 { 918 {
915 Messaging.Instance.OnMessage(WixErrors.DuplicateComponentGuids(row.SourceLineNumbers, row.Component, row.Guid)); 919 this.Messaging.Write(ErrorMessages.DuplicateComponentGuids(row.SourceLineNumbers, row.Component, row.Guid));
916 } 920 }
917 } 921 }
918 922
@@ -929,6 +933,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
929 private void UpdateControlText(Output output) 933 private void UpdateControlText(Output output)
930 { 934 {
931 var command = new UpdateControlTextCommand(); 935 var command = new UpdateControlTextCommand();
936 command.Messaging = this.Messaging;
932 command.BBControlTable = output.Tables["BBControl"]; 937 command.BBControlTable = output.Tables["BBControl"];
933 command.WixBBControlTable = output.Tables["WixBBControl"]; 938 command.WixBBControlTable = output.Tables["WixBBControl"];
934 command.ControlTable = output.Tables["Control"]; 939 command.ControlTable = output.Tables["Control"];
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs
index 49440cea..800ebac0 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs
@@ -6,11 +6,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
6 using System.Collections.Generic; 6 using System.Collections.Generic;
7 using System.Globalization; 7 using System.Globalization;
8 using System.IO; 8 using System.IO;
9 using WixToolset.Core.Native;
9 using WixToolset.Data; 10 using WixToolset.Data;
11 using WixToolset.Data.WindowsInstaller;
10 using WixToolset.Extensibility; 12 using WixToolset.Extensibility;
13 using WixToolset.Extensibility.Services;
11 using WixToolset.Msi; 14 using WixToolset.Msi;
12 using WixToolset.Core.Native;
13 using WixToolset.Data.WindowsInstaller;
14 15
15 internal class BindTransformCommand 16 internal class BindTransformCommand
16 { 17 {
@@ -22,6 +23,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
22 23
23 public Output Transform { private get; set; } 24 public Output Transform { private get; set; }
24 25
26 public IMessaging Messaging { private get; set; }
27
25 public string OutputPath { private get; set; } 28 public string OutputPath { private get; set; }
26 29
27 public void Execute() 30 public void Execute()
@@ -197,7 +200,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
197 if (((int)TransformFlags.ValidateUpgradeCode & transformFlags) != 0 && 200 if (((int)TransformFlags.ValidateUpgradeCode & transformFlags) != 0 &&
198 (String.IsNullOrEmpty(targetUpgradeCode) || String.IsNullOrEmpty(updatedUpgradeCode))) 201 (String.IsNullOrEmpty(targetUpgradeCode) || String.IsNullOrEmpty(updatedUpgradeCode)))
199 { 202 {
200 Messaging.Instance.OnMessage(WixErrors.BothUpgradeCodesRequired()); 203 this.Messaging.Write(ErrorMessages.BothUpgradeCodesRequired());
201 } 204 }
202 205
203 string emptyFile = null; 206 string emptyFile = null;
@@ -276,7 +279,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
276 { 279 {
277 if (RowOperation.Add == fileRow.Operation) 280 if (RowOperation.Add == fileRow.Operation)
278 { 281 {
279 Messaging.Instance.OnMessage(WixErrors.InvalidAddedFileRowWithoutSequence(fileRow.SourceLineNumbers, (string)fileRow[0])); 282 this.Messaging.Write(ErrorMessages.InvalidAddedFileRowWithoutSequence(fileRow.SourceLineNumbers, (string)fileRow[0]));
280 break; 283 break;
281 } 284 }
282 285
@@ -384,7 +387,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
384 //} 387 //}
385 388
386 // Any errors encountered up to this point can cause errors during generation. 389 // Any errors encountered up to this point can cause errors during generation.
387 if (Messaging.Instance.EncounteredError) 390 if (this.Messaging.EncounteredError)
388 { 391 {
389 return; 392 return;
390 } 393 }
@@ -419,7 +422,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
419 } 422 }
420 else 423 else
421 { 424 {
422 Messaging.Instance.OnMessage(WixErrors.NoDifferencesInTransform(this.Transform.SourceLineNumbers)); 425 this.Messaging.Write(ErrorMessages.NoDifferencesInTransform(this.Transform.SourceLineNumbers));
423 } 426 }
424 } 427 }
425 } 428 }
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs
index fde781a3..0c167699 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs
@@ -4,13 +4,13 @@ namespace WixToolset.Core.WindowsInstaller.Bind
4{ 4{
5 using System; 5 using System;
6 using System.Collections; 6 using System.Collections;
7 using System.Collections.Generic;
8 using System.IO; 7 using System.IO;
9 using System.Linq; 8 using System.Linq;
10 using System.Threading; 9 using System.Threading;
11 using WixToolset.Core.Bind; 10 using WixToolset.Core.Bind;
12 using WixToolset.Core.Native; 11 using WixToolset.Core.Native;
13 using WixToolset.Data; 12 using WixToolset.Data;
13 using WixToolset.Extensibility.Services;
14 14
15 /// <summary> 15 /// <summary>
16 /// Builds cabinets using multiple threads. This implements a thread pool that generates cabinets with multiple 16 /// Builds cabinets using multiple threads. This implements a thread pool that generates cabinets with multiple
@@ -25,16 +25,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
25 // Address of Binder's callback function for Cabinet Splitting 25 // Address of Binder's callback function for Cabinet Splitting
26 private IntPtr newCabNamesCallBackAddress; 26 private IntPtr newCabNamesCallBackAddress;
27 27
28 public int MaximumCabinetSizeForLargeFileSplitting { get; set; }
29
30 public int MaximumUncompressedMediaSize { get; set; }
31
32 /// <summary> 28 /// <summary>
33 /// Instantiate a new CabinetBuilder. 29 /// Instantiate a new CabinetBuilder.
34 /// </summary> 30 /// </summary>
35 /// <param name="threadCount">number of threads to use</param> 31 /// <param name="threadCount">number of threads to use</param>
36 /// <param name="newCabNamesCallBackAddress">Address of Binder's callback function for Cabinet Splitting</param> 32 /// <param name="newCabNamesCallBackAddress">Address of Binder's callback function for Cabinet Splitting</param>
37 public CabinetBuilder(int threadCount, IntPtr newCabNamesCallBackAddress) 33 public CabinetBuilder(IMessaging messaging, int threadCount, IntPtr newCabNamesCallBackAddress)
38 { 34 {
39 if (0 >= threadCount) 35 if (0 >= threadCount)
40 { 36 {
@@ -43,13 +39,19 @@ namespace WixToolset.Core.WindowsInstaller.Bind
43 39
44 this.cabinetWorkItems = new Queue(); 40 this.cabinetWorkItems = new Queue();
45 this.lockObject = new object(); 41 this.lockObject = new object();
46 42 this.Messaging = messaging;
47 this.threadCount = threadCount; 43 this.threadCount = threadCount;
48 44
49 // Set Address of Binder's callback function for Cabinet Splitting 45 // Set Address of Binder's callback function for Cabinet Splitting
50 this.newCabNamesCallBackAddress = newCabNamesCallBackAddress; 46 this.newCabNamesCallBackAddress = newCabNamesCallBackAddress;
51 } 47 }
52 48
49 private IMessaging Messaging { get; }
50
51 public int MaximumCabinetSizeForLargeFileSplitting { get; set; }
52
53 public int MaximumUncompressedMediaSize { get; set; }
54
53 /// <summary> 55 /// <summary>
54 /// Enqueues a CabinetWorkItem to the queue. 56 /// Enqueues a CabinetWorkItem to the queue.
55 /// </summary> 57 /// </summary>
@@ -119,11 +121,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
119 } 121 }
120 catch (WixException we) 122 catch (WixException we)
121 { 123 {
122 Messaging.Instance.OnMessage(we.Error); 124 this.Messaging.Write(we.Error);
123 } 125 }
124 catch (Exception e) 126 catch (Exception e)
125 { 127 {
126 Messaging.Instance.OnMessage(WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace)); 128 this.Messaging.Write(ErrorMessages.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
127 } 129 }
128 } 130 }
129 131
@@ -133,7 +135,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
133 /// <param name="cabinetWorkItem">CabinetWorkItem containing information about the cabinet to create.</param> 135 /// <param name="cabinetWorkItem">CabinetWorkItem containing information about the cabinet to create.</param>
134 private void CreateCabinet(CabinetWorkItem cabinetWorkItem) 136 private void CreateCabinet(CabinetWorkItem cabinetWorkItem)
135 { 137 {
136 Messaging.Instance.OnMessage(WixVerboses.CreateCabinet(cabinetWorkItem.CabinetFile)); 138 this.Messaging.Write(VerboseMessages.CreateCabinet(cabinetWorkItem.CabinetFile));
137 139
138 int maxCabinetSize = 0; // The value of 0 corresponds to default of 2GB which means no cabinet splitting 140 int maxCabinetSize = 0; // The value of 0 corresponds to default of 2GB which means no cabinet splitting
139 ulong maxPreCompressedSizeInBytes = 0; 141 ulong maxPreCompressedSizeInBytes = 0;
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetResolver.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetResolver.cs
index 370d4b9c..cf8eb338 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetResolver.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetResolver.cs
@@ -109,7 +109,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
109 } 109 }
110 catch (ArgumentException) 110 catch (ArgumentException)
111 { 111 {
112 throw new WixException(WixErrors.IllegalCharactersInPath(path)); 112 throw new WixException(ErrorMessages.IllegalCharactersInPath(path));
113 } 113 }
114 } 114 }
115 } 115 }
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs
index 0c0aea1f..056f92a7 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs
@@ -10,17 +10,21 @@ namespace WixToolset.Core.WindowsInstaller.Bind
10 using WixToolset.Core.Native; 10 using WixToolset.Core.Native;
11 using WixToolset.Data; 11 using WixToolset.Data;
12 using WixToolset.Data.Tuples; 12 using WixToolset.Data.Tuples;
13 using WixToolset.Extensibility.Services;
13 14
14 /// <summary> 15 /// <summary>
15 /// Set the guids for components with generatable guids. 16 /// Set the guids for components with generatable guids.
16 /// </summary> 17 /// </summary>
17 internal class CalculateComponentGuids 18 internal class CalculateComponentGuids
18 { 19 {
19 public CalculateComponentGuids(IntermediateSection section) 20 public CalculateComponentGuids(IMessaging messaging, IntermediateSection section)
20 { 21 {
22 this.Messaging = messaging;
21 this.Section = section; 23 this.Section = section;
22 } 24 }
23 25
26 private IMessaging Messaging { get; }
27
24 private IntermediateSection Section { get; } 28 private IntermediateSection Section { get; }
25 29
26 public void Execute() 30 public void Execute()
@@ -43,7 +47,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
43 47
44 if (String.IsNullOrEmpty(componentRow.KeyPath) || odbcDataSourceKeyPath) 48 if (String.IsNullOrEmpty(componentRow.KeyPath) || odbcDataSourceKeyPath)
45 { 49 {
46 Messaging.Instance.OnMessage(WixErrors.IllegalComponentWithAutoGeneratedGuid(componentRow.SourceLineNumbers)); 50 this.Messaging.Write(ErrorMessages.IllegalComponentWithAutoGeneratedGuid(componentRow.SourceLineNumbers));
47 continue; 51 continue;
48 } 52 }
49 53
@@ -143,13 +147,13 @@ namespace WixToolset.Core.WindowsInstaller.Bind
143 path.StartsWith(@"StartMenuFolder\programs", StringComparison.Ordinal) || 147 path.StartsWith(@"StartMenuFolder\programs", StringComparison.Ordinal) ||
144 path.StartsWith(@"WindowsFolder\fonts", StringComparison.Ordinal)) 148 path.StartsWith(@"WindowsFolder\fonts", StringComparison.Ordinal))
145 { 149 {
146 Messaging.Instance.OnMessage(WixErrors.IllegalPathForGeneratedComponentGuid(componentRow.SourceLineNumbers, fileRow.Component_, path)); 150 this.Messaging.Write(ErrorMessages.IllegalPathForGeneratedComponentGuid(componentRow.SourceLineNumbers, fileRow.Component_, path));
147 } 151 }
148 152
149 // if component has more than one file, the key path must be versioned 153 // if component has more than one file, the key path must be versioned
150 if (1 < numFilesInComponent && String.IsNullOrEmpty(fileRow.Version)) 154 if (1 < numFilesInComponent && String.IsNullOrEmpty(fileRow.Version))
151 { 155 {
152 Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentUnversionedKeypath(componentRow.SourceLineNumbers)); 156 this.Messaging.Write(ErrorMessages.IllegalGeneratedGuidComponentUnversionedKeypath(componentRow.SourceLineNumbers));
153 } 157 }
154 } 158 }
155 else 159 else
@@ -157,13 +161,13 @@ namespace WixToolset.Core.WindowsInstaller.Bind
157 // not a key path, so it must be an unversioned file if component has more than one file 161 // not a key path, so it must be an unversioned file if component has more than one file
158 if (1 < numFilesInComponent && !String.IsNullOrEmpty(fileRow.Version)) 162 if (1 < numFilesInComponent && !String.IsNullOrEmpty(fileRow.Version))
159 { 163 {
160 Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentVersionedNonkeypath(componentRow.SourceLineNumbers)); 164 this.Messaging.Write(ErrorMessages.IllegalGeneratedGuidComponentVersionedNonkeypath(componentRow.SourceLineNumbers));
161 } 165 }
162 } 166 }
163 } 167 }
164 168
165 // if the rules were followed, reward with a generated guid 169 // if the rules were followed, reward with a generated guid
166 if (!Messaging.Instance.EncounteredError) 170 if (!this.Messaging.EncounteredError)
167 { 171 {
168 componentRow.ComponentId = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, path).ToString("B").ToUpperInvariant(); 172 componentRow.ComponentId = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, path).ToString("B").ToUpperInvariant();
169 } 173 }
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs
index 559d440c..13408312 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs
@@ -12,13 +12,16 @@ namespace WixToolset.Core.WindowsInstaller.Bind
12 using WixToolset.Data.WindowsInstaller; 12 using WixToolset.Data.WindowsInstaller;
13 using WixToolset.Data.WindowsInstaller.Rows; 13 using WixToolset.Data.WindowsInstaller.Rows;
14 using WixToolset.Extensibility; 14 using WixToolset.Extensibility;
15 using WixToolset.Extensibility.Services;
15 16
16 internal class CopyTransformDataCommand 17 internal class CopyTransformDataCommand
17 { 18 {
18 public bool CopyOutFileRows { private get; set; } 19 public bool CopyOutFileRows { private get; set; }
19 20
20 public IEnumerable<IBinderExtension> Extensions { private get; set; } 21 public IEnumerable<IBinderExtension> Extensions { private get; set; }
21 22
23 public IMessaging Messaging { private get; set; }
24
22 public Output Output { private get; set; } 25 public Output Output { private get; set; }
23 26
24 public TableDefinitionCollection TableDefinitions { private get; set; } 27 public TableDefinitionCollection TableDefinitions { private get; set; }
@@ -465,14 +468,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
465 { 468 {
466 if (seqDuplicateFiles < seqInstallFiles) 469 if (seqDuplicateFiles < seqInstallFiles)
467 { 470 {
468 throw new WixException(WixErrors.InsertInvalidSequenceActionOrder(mainFileRow.SourceLineNumbers, iesTable.Name, "InstallFiles", "DuplicateFiles", wixPatchAction.Action)); 471 throw new WixException(ErrorMessages.InsertInvalidSequenceActionOrder(mainFileRow.SourceLineNumbers, iesTable.Name, "InstallFiles", "DuplicateFiles", wixPatchAction.Action));
469 } 472 }
470 else 473 else
471 { 474 {
472 sequence = (seqDuplicateFiles + seqInstallFiles) / 2; 475 sequence = (seqDuplicateFiles + seqInstallFiles) / 2;
473 if (seqInstallFiles == sequence || seqDuplicateFiles == sequence) 476 if (seqInstallFiles == sequence || seqDuplicateFiles == sequence)
474 { 477 {
475 throw new WixException(WixErrors.InsertSequenceNoSpace(mainFileRow.SourceLineNumbers, iesTable.Name, "InstallFiles", "DuplicateFiles", wixPatchAction.Action)); 478 throw new WixException(ErrorMessages.InsertSequenceNoSpace(mainFileRow.SourceLineNumbers, iesTable.Name, "InstallFiles", "DuplicateFiles", wixPatchAction.Action));
476 } 479 }
477 } 480 }
478 } 481 }
@@ -579,7 +582,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
579 // Make sure all changes to non keypath files also had a change in the keypath. 582 // Make sure all changes to non keypath files also had a change in the keypath.
580 if (!componentWithChangedKeyPath.ContainsKey(componentFile.Key) && componentKeyPath.ContainsKey(componentFile.Key)) 583 if (!componentWithChangedKeyPath.ContainsKey(componentFile.Key) && componentKeyPath.ContainsKey(componentFile.Key))
581 { 584 {
582 Messaging.Instance.OnMessage(WixWarnings.UpdateOfNonKeyPathFile((string)componentFile.Value, (string)componentFile.Key, (string)componentKeyPath[componentFile.Key])); 585 this.Messaging.Write(WarningMessages.UpdateOfNonKeyPathFile((string)componentFile.Value, (string)componentFile.Key, (string)componentKeyPath[componentFile.Key]));
583 } 586 }
584 } 587 }
585 } 588 }
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs
index 0aa50bd9..28e7f6df 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs
@@ -16,6 +16,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
16 using WixToolset.Data.WindowsInstaller; 16 using WixToolset.Data.WindowsInstaller;
17 using WixToolset.Data.WindowsInstaller.Rows; 17 using WixToolset.Data.WindowsInstaller.Rows;
18 using WixToolset.Extensibility; 18 using WixToolset.Extensibility;
19 using WixToolset.Extensibility.Services;
19 20
20 /// <summary> 21 /// <summary>
21 /// Creates cabinet files. 22 /// Creates cabinet files.
@@ -45,6 +46,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
45 46
46 public string CabCachePath { private get; set; } 47 public string CabCachePath { private get; set; }
47 48
49 public IMessaging Messaging { private get; set; }
50
48 public string TempFilesLocation { private get; set; } 51 public string TempFilesLocation { private get; set; }
49 52
50 /// <summary> 53 /// <summary>
@@ -85,7 +88,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
85 this.SetCabbingThreadCount(); 88 this.SetCabbingThreadCount();
86 89
87 // Send Binder object to Facilitate NewCabNamesCallBack Callback 90 // Send Binder object to Facilitate NewCabNamesCallBack Callback
88 CabinetBuilder cabinetBuilder = new CabinetBuilder(this.CabbingThreadCount, Marshal.GetFunctionPointerForDelegate(this.newCabNamesCallBack)); 91 CabinetBuilder cabinetBuilder = new CabinetBuilder(this.Messaging, this.CabbingThreadCount, Marshal.GetFunctionPointerForDelegate(this.newCabNamesCallBack));
89 92
90 // Supply Compile MediaTemplate Attributes to Cabinet Builder 93 // Supply Compile MediaTemplate Attributes to Cabinet Builder
91 this.GetMediaTemplateAttributes(out var MaximumCabinetSizeForLargeFileSplitting, out var MaximumUncompressedMediaSize); 94 this.GetMediaTemplateAttributes(out var MaximumCabinetSizeForLargeFileSplitting, out var MaximumUncompressedMediaSize);
@@ -120,14 +123,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
120 } 123 }
121 124
122 // stop processing if an error previously occurred 125 // stop processing if an error previously occurred
123 if (Messaging.Instance.EncounteredError) 126 if (this.Messaging.EncounteredError)
124 { 127 {
125 return; 128 return;
126 } 129 }
127 130
128 // create queued cabinets with multiple threads 131 // create queued cabinets with multiple threads
129 cabinetBuilder.CreateQueuedCabinets(); 132 cabinetBuilder.CreateQueuedCabinets();
130 if (Messaging.Instance.EncounteredError) 133 if (this.Messaging.EncounteredError)
131 { 134 {
132 return; 135 return;
133 } 136 }
@@ -152,7 +155,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
152 155
153 if (0 >= this.CabbingThreadCount) 156 if (0 >= this.CabbingThreadCount)
154 { 157 {
155 throw new WixException(WixErrors.IllegalEnvironmentVariable("NUMBER_OF_PROCESSORS", numberOfProcessors)); 158 throw new WixException(ErrorMessages.IllegalEnvironmentVariable("NUMBER_OF_PROCESSORS", numberOfProcessors));
156 } 159 }
157 } 160 }
158 else // default to 1 if the environment variable is not set 161 else // default to 1 if the environment variable is not set
@@ -160,15 +163,15 @@ namespace WixToolset.Core.WindowsInstaller.Bind
160 this.CabbingThreadCount = 1; 163 this.CabbingThreadCount = 1;
161 } 164 }
162 165
163 Messaging.Instance.OnMessage(WixVerboses.SetCabbingThreadCount(this.CabbingThreadCount.ToString())); 166 this.Messaging.Write(VerboseMessages.SetCabbingThreadCount(this.CabbingThreadCount.ToString()));
164 } 167 }
165 catch (ArgumentException) 168 catch (ArgumentException)
166 { 169 {
167 throw new WixException(WixErrors.IllegalEnvironmentVariable("NUMBER_OF_PROCESSORS", numberOfProcessors)); 170 throw new WixException(ErrorMessages.IllegalEnvironmentVariable("NUMBER_OF_PROCESSORS", numberOfProcessors));
168 } 171 }
169 catch (FormatException) 172 catch (FormatException)
170 { 173 {
171 throw new WixException(WixErrors.IllegalEnvironmentVariable("NUMBER_OF_PROCESSORS", numberOfProcessors)); 174 throw new WixException(ErrorMessages.IllegalEnvironmentVariable("NUMBER_OF_PROCESSORS", numberOfProcessors));
172 } 175 }
173 } 176 }
174 } 177 }
@@ -202,11 +205,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
202 // If building a patch, remind them to run -p for torch. 205 // If building a patch, remind them to run -p for torch.
203 if (OutputType.Patch == output.Type) 206 if (OutputType.Patch == output.Type)
204 { 207 {
205 Messaging.Instance.OnMessage(WixWarnings.EmptyCabinet(mediaRow.SourceLineNumbers, cabinetName, true)); 208 this.Messaging.Write(WarningMessages.EmptyCabinet(mediaRow.SourceLineNumbers, cabinetName, true));
206 } 209 }
207 else 210 else
208 { 211 {
209 Messaging.Instance.OnMessage(WixWarnings.EmptyCabinet(mediaRow.SourceLineNumbers, cabinetName)); 212 this.Messaging.Write(WarningMessages.EmptyCabinet(mediaRow.SourceLineNumbers, cabinetName));
210 } 213 }
211 } 214 }
212 215
@@ -223,7 +226,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
223 } 226 }
224 else // reuse the cabinet from the cabinet cache. 227 else // reuse the cabinet from the cabinet cache.
225 { 228 {
226 Messaging.Instance.OnMessage(WixVerboses.ReusingCabCache(mediaRow.SourceLineNumbers, mediaRow.Cabinet, resolvedCabinet.Path)); 229 this.Messaging.Write(VerboseMessages.ReusingCabCache(mediaRow.SourceLineNumbers, mediaRow.Cabinet, resolvedCabinet.Path));
227 230
228 try 231 try
229 { 232 {
@@ -237,7 +240,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
237 } 240 }
238 catch (Exception e) 241 catch (Exception e)
239 { 242 {
240 Messaging.Instance.OnMessage(WixWarnings.CannotUpdateCabCache(mediaRow.SourceLineNumbers, resolvedCabinet.Path, e.Message)); 243 this.Messaging.Write(WarningMessages.CannotUpdateCabCache(mediaRow.SourceLineNumbers, resolvedCabinet.Path, e.Message));
241 } 244 }
242 } 245 }
243 246
@@ -303,7 +306,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
303 if (!mutex.WaitOne(0, false)) // Check if you can get the lock 306 if (!mutex.WaitOne(0, false)) // Check if you can get the lock
304 { 307 {
305 // Cound not get the Lock 308 // Cound not get the Lock
306 Messaging.Instance.OnMessage(WixVerboses.CabinetsSplitInParallel()); 309 this.Messaging.Write(VerboseMessages.CabinetsSplitInParallel());
307 mutex.WaitOne(); // Wait on other thread 310 mutex.WaitOne(); // Wait on other thread
308 } 311 }
309 312
@@ -333,7 +336,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
333 // Check if File Transfer was added 336 // Check if File Transfer was added
334 if (!transferAdded) 337 if (!transferAdded)
335 { 338 {
336 throw new WixException(WixErrors.SplitCabinetCopyRegistrationFailed(newCabinetName, firstCabinetName)); 339 throw new WixException(ErrorMessages.SplitCabinetCopyRegistrationFailed(newCabinetName, firstCabinetName));
337 } 340 }
338 341
339 // Add the new Cabinets to media table using LastSequence of Base Cabinet 342 // Add the new Cabinets to media table using LastSequence of Base Cabinet
@@ -365,14 +368,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
365 if (newCabinetName.Equals(mediaRow.Cabinet, StringComparison.InvariantCultureIgnoreCase)) 368 if (newCabinetName.Equals(mediaRow.Cabinet, StringComparison.InvariantCultureIgnoreCase))
366 { 369 {
367 // Name Collision of generated Split Cabinet Name and user Specified Cab name for current row 370 // Name Collision of generated Split Cabinet Name and user Specified Cab name for current row
368 throw new WixException(WixErrors.SplitCabinetNameCollision(newCabinetName, firstCabinetName)); 371 throw new WixException(ErrorMessages.SplitCabinetNameCollision(newCabinetName, firstCabinetName));
369 } 372 }
370 } 373 }
371 374
372 // Check if the last Split Cabinet was found in the Media Table 375 // Check if the last Split Cabinet was found in the Media Table
373 if (!lastSplitCabinetFound) 376 if (!lastSplitCabinetFound)
374 { 377 {
375 throw new WixException(WixErrors.SplitCabinetInsertionFailed(newCabinetName, firstCabinetName, lastCabinetOfThisSequence)); 378 throw new WixException(ErrorMessages.SplitCabinetInsertionFailed(newCabinetName, firstCabinetName, lastCabinetOfThisSequence));
376 } 379 }
377 380
378 // The new Row has to be inserted just after the last cab in this cabinet split chain according to DiskID Sort 381 // The new Row has to be inserted just after the last cab in this cabinet split chain according to DiskID Sort
@@ -454,11 +457,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
454 } 457 }
455 catch (FormatException) 458 catch (FormatException)
456 { 459 {
457 throw new WixException(WixErrors.IllegalEnvironmentVariable("WIX_MCSLFS", mcslfsString)); 460 throw new WixException(ErrorMessages.IllegalEnvironmentVariable("WIX_MCSLFS", mcslfsString));
458 } 461 }
459 catch (OverflowException) 462 catch (OverflowException)
460 { 463 {
461 throw new WixException(WixErrors.MaximumCabinetSizeForLargeFileSplittingTooLarge(null, maxCabSizeForLargeFileInMB, MaxValueOfMaxCabSizeForLargeFileSplitting)); 464 throw new WixException(ErrorMessages.MaximumCabinetSizeForLargeFileSplittingTooLarge(null, maxCabSizeForLargeFileInMB, MaxValueOfMaxCabSizeForLargeFileSplitting));
462 } 465 }
463 466
464 try 467 try
@@ -476,11 +479,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
476 } 479 }
477 catch (FormatException) 480 catch (FormatException)
478 { 481 {
479 throw new WixException(WixErrors.IllegalEnvironmentVariable("WIX_MUMS", mumsString)); 482 throw new WixException(ErrorMessages.IllegalEnvironmentVariable("WIX_MUMS", mumsString));
480 } 483 }
481 catch (OverflowException) 484 catch (OverflowException)
482 { 485 {
483 throw new WixException(WixErrors.MaximumUncompressedMediaSizeTooLarge(null, maxPreCompressedSizeInMB)); 486 throw new WixException(ErrorMessages.MaximumUncompressedMediaSizeTooLarge(null, maxPreCompressedSizeInMB));
484 } 487 }
485 488
486 maxCabSizeForLargeFileSplitting = maxCabSizeForLargeFileInMB; 489 maxCabSizeForLargeFileSplitting = maxCabSizeForLargeFileInMB;
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateIdtFileCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateIdtFileCommand.cs
index 1fc7d068..9afb3260 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateIdtFileCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateIdtFileCommand.cs
@@ -8,17 +8,21 @@ namespace WixToolset.Core.WindowsInstaller.Bind
8 using System.Text; 8 using System.Text;
9 using WixToolset.Data; 9 using WixToolset.Data;
10 using WixToolset.Data.WindowsInstaller; 10 using WixToolset.Data.WindowsInstaller;
11 using WixToolset.Extensibility.Services;
11 12
12 internal class CreateIdtFileCommand 13 internal class CreateIdtFileCommand
13 { 14 {
14 public CreateIdtFileCommand(Table table, int codepage, string intermediateFolder, bool keepAddedColumns) 15 public CreateIdtFileCommand(IMessaging messaging, Table table, int codepage, string intermediateFolder, bool keepAddedColumns)
15 { 16 {
17 this.Messaging = messaging;
16 this.Table = table; 18 this.Table = table;
17 this.Codepage = codepage; 19 this.Codepage = codepage;
18 this.IntermediateFolder = intermediateFolder; 20 this.IntermediateFolder = intermediateFolder;
19 this.KeepAddedColumns = keepAddedColumns; 21 this.KeepAddedColumns = keepAddedColumns;
20 } 22 }
21 23
24 private IMessaging Messaging { get; }
25
22 private Table Table { get; } 26 private Table Table { get; }
23 27
24 private int Codepage { get; set; } 28 private int Codepage { get; set; }
@@ -67,7 +71,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
67 71
68 if (TableDefinition.MaxColumnsInRealTable < table.Definition.Columns.Count) 72 if (TableDefinition.MaxColumnsInRealTable < table.Definition.Columns.Count)
69 { 73 {
70 throw new WixException(WixDataErrors.TooManyColumnsInRealTable(table.Definition.Name, table.Definition.Columns.Count, TableDefinition.MaxColumnsInRealTable)); 74 throw new WixException(ErrorMessages.TooManyColumnsInRealTable(table.Definition.Name, table.Definition.Columns.Count, TableDefinition.MaxColumnsInRealTable));
71 } 75 }
72 76
73 // Tack on the table header, and flush before we start writing bytes directly to the stream. 77 // Tack on the table header, and flush before we start writing bytes directly to the stream.
@@ -98,7 +102,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
98 } 102 }
99 catch (EncoderFallbackException) 103 catch (EncoderFallbackException)
100 { 104 {
101 Messaging.Instance.OnMessage(WixDataErrors.InvalidStringForCodepage(row.SourceLineNumbers, Convert.ToString(writer.Encoding.WindowsCodePage, CultureInfo.InvariantCulture))); 105 this.Messaging.Write(ErrorMessages.InvalidStringForCodepage(row.SourceLineNumbers, Convert.ToString(writer.Encoding.WindowsCodePage, CultureInfo.InvariantCulture)));
102 106
103 rowBytes = convertEncoding.GetBytes(rowString); 107 rowBytes = convertEncoding.GetBytes(rowString);
104 } 108 }
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs
index a31c8079..e1777246 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs
@@ -15,18 +15,22 @@ namespace WixToolset.Core.WindowsInstaller.Bind
15 using WixToolset.Core.Native; 15 using WixToolset.Core.Native;
16 using WixToolset.Core.Bind; 16 using WixToolset.Core.Bind;
17 using WixToolset.Data.Tuples; 17 using WixToolset.Data.Tuples;
18 using WixToolset.Extensibility.Services;
18 19
19 /// <summary> 20 /// <summary>
20 /// Retrieve files information and extract them from merge modules. 21 /// Retrieve files information and extract them from merge modules.
21 /// </summary> 22 /// </summary>
22 internal class ExtractMergeModuleFilesCommand 23 internal class ExtractMergeModuleFilesCommand
23 { 24 {
24 public ExtractMergeModuleFilesCommand(IntermediateSection section, List<WixMergeTuple> wixMergeTuples) 25 public ExtractMergeModuleFilesCommand(IMessaging messaging, IntermediateSection section, List<WixMergeTuple> wixMergeTuples)
25 { 26 {
27 this.Messaging = messaging;
26 this.Section = section; 28 this.Section = section;
27 this.WixMergeTuples = wixMergeTuples; 29 this.WixMergeTuples = wixMergeTuples;
28 } 30 }
29 31
32 private IMessaging Messaging { get; }
33
30 private IntermediateSection Section { get; } 34 private IntermediateSection Section { get; }
31 35
32 private List<WixMergeTuple> WixMergeTuples { get; } 36 private List<WixMergeTuple> WixMergeTuples { get; }
@@ -121,11 +125,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
121 // If case-sensitive collision with another merge module or a user-authored file identifier. 125 // If case-sensitive collision with another merge module or a user-authored file identifier.
122 if (indexedFileFacades.TryGetValue(mergeModuleFileFacade.File.File, out var collidingFacade)) 126 if (indexedFileFacades.TryGetValue(mergeModuleFileFacade.File.File, out var collidingFacade))
123 { 127 {
124 Messaging.Instance.OnMessage(WixErrors.DuplicateModuleFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, collidingFacade.File.File)); 128 this.Messaging.Write(ErrorMessages.DuplicateModuleFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, collidingFacade.File.File));
125 } 129 }
126 else if (uniqueModuleFileIdentifiers.TryGetValue(mergeModuleFileFacade.File.File, out collidingFacade)) // case-insensitive collision with another file identifier in the same merge module 130 else if (uniqueModuleFileIdentifiers.TryGetValue(mergeModuleFileFacade.File.File, out collidingFacade)) // case-insensitive collision with another file identifier in the same merge module
127 { 131 {
128 Messaging.Instance.OnMessage(WixErrors.DuplicateModuleCaseInsensitiveFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, mergeModuleFileFacade.File.File, collidingFacade.File.File)); 132 this.Messaging.Write(ErrorMessages.DuplicateModuleCaseInsensitiveFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, mergeModuleFileFacade.File.File, collidingFacade.File.File));
129 } 133 }
130 else // no collision 134 else // no collision
131 { 135 {
@@ -152,23 +156,23 @@ namespace WixToolset.Core.WindowsInstaller.Bind
152 int moduleInstallerVersion = Convert.ToInt32(moduleInstallerVersionString, CultureInfo.InvariantCulture); 156 int moduleInstallerVersion = Convert.ToInt32(moduleInstallerVersionString, CultureInfo.InvariantCulture);
153 if (moduleInstallerVersion > this.OutputInstallerVersion) 157 if (moduleInstallerVersion > this.OutputInstallerVersion)
154 { 158 {
155 Messaging.Instance.OnMessage(WixWarnings.InvalidHigherInstallerVersionInModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, moduleInstallerVersion, this.OutputInstallerVersion)); 159 this.Messaging.Write(WarningMessages.InvalidHigherInstallerVersionInModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, moduleInstallerVersion, this.OutputInstallerVersion));
156 } 160 }
157 } 161 }
158 catch (FormatException) 162 catch (FormatException)
159 { 163 {
160 throw new WixException(WixErrors.MissingOrInvalidModuleInstallerVersion(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, wixMergeRow.SourceFile, moduleInstallerVersionString)); 164 throw new WixException(ErrorMessages.MissingOrInvalidModuleInstallerVersion(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, wixMergeRow.SourceFile, moduleInstallerVersionString));
161 } 165 }
162 } 166 }
163 } 167 }
164 } 168 }
165 catch (FileNotFoundException) 169 catch (FileNotFoundException)
166 { 170 {
167 throw new WixException(WixErrors.FileNotFound(wixMergeRow.SourceLineNumbers, wixMergeRow.SourceFile)); 171 throw new WixException(ErrorMessages.FileNotFound(wixMergeRow.SourceLineNumbers, wixMergeRow.SourceFile));
168 } 172 }
169 catch (Win32Exception) 173 catch (Win32Exception)
170 { 174 {
171 throw new WixException(WixErrors.CannotOpenMergeModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, wixMergeRow.SourceFile)); 175 throw new WixException(ErrorMessages.CannotOpenMergeModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, wixMergeRow.SourceFile));
172 } 176 }
173 177
174 return containsFiles; 178 return containsFiles;
@@ -187,7 +191,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
187 } 191 }
188 catch (FormatException) 192 catch (FormatException)
189 { 193 {
190 Messaging.Instance.OnMessage(WixErrors.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, mergeId, wixMergeRow.Language.ToString())); 194 this.Messaging.Write(ErrorMessages.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, mergeId, wixMergeRow.Language.ToString()));
191 return; 195 return;
192 } 196 }
193 197
@@ -210,16 +214,16 @@ namespace WixToolset.Core.WindowsInstaller.Bind
210 } 214 }
211 catch (FileNotFoundException) 215 catch (FileNotFoundException)
212 { 216 {
213 throw new WixException(WixErrors.CabFileDoesNotExist(moduleCabPath, wixMergeRow.SourceFile, mergeIdPath)); 217 throw new WixException(ErrorMessages.CabFileDoesNotExist(moduleCabPath, wixMergeRow.SourceFile, mergeIdPath));
214 } 218 }
215 catch 219 catch
216 { 220 {
217 throw new WixException(WixErrors.CabExtractionFailed(moduleCabPath, wixMergeRow.SourceFile, mergeIdPath)); 221 throw new WixException(ErrorMessages.CabExtractionFailed(moduleCabPath, wixMergeRow.SourceFile, mergeIdPath));
218 } 222 }
219 } 223 }
220 catch (COMException ce) 224 catch (COMException ce)
221 { 225 {
222 throw new WixException(WixErrors.UnableToOpenModule(wixMergeRow.SourceLineNumbers, wixMergeRow.SourceFile, ce.Message)); 226 throw new WixException(ErrorMessages.UnableToOpenModule(wixMergeRow.SourceLineNumbers, wixMergeRow.SourceFile, ce.Message));
223 } 227 }
224 finally 228 finally
225 { 229 {
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs
index e4e66559..ee7cc61b 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs
@@ -13,6 +13,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
13 using WixToolset.Msi; 13 using WixToolset.Msi;
14 using WixToolset.Core.Native; 14 using WixToolset.Core.Native;
15 using WixToolset.Data.WindowsInstaller; 15 using WixToolset.Data.WindowsInstaller;
16 using WixToolset.Extensibility.Services;
16 17
17 internal class GenerateDatabaseCommand 18 internal class GenerateDatabaseCommand
18 { 19 {
@@ -25,6 +26,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
25 /// </summary> 26 /// </summary>
26 public bool KeepAddedColumns { private get; set; } 27 public bool KeepAddedColumns { private get; set; }
27 28
29 public IMessaging Messaging { private get; set; }
30
28 public Output Output { private get; set; } 31 public Output Output { private get; set; }
29 32
30 public string OutputPath { private get; set; } 33 public string OutputPath { private get; set; }
@@ -177,7 +180,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
177 try 180 try
178 { 181 {
179 //db.ImportTable(this.Output.Codepage, importTable, baseDirectory, this.KeepAddedColumns); 182 //db.ImportTable(this.Output.Codepage, importTable, baseDirectory, this.KeepAddedColumns);
180 var command = new CreateIdtFileCommand(importTable, this.Output.Codepage, baseDirectory, this.KeepAddedColumns); 183 var command = new CreateIdtFileCommand(this.Messaging, importTable, this.Output.Codepage, baseDirectory, this.KeepAddedColumns);
181 command.Execute(); 184 command.Execute();
182 185
183 db.Import(command.IdtPath); 186 db.Import(command.IdtPath);
@@ -262,11 +265,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
262 { 265 {
263 if (0xA1 == e.NativeErrorCode) // ERROR_BAD_PATHNAME 266 if (0xA1 == e.NativeErrorCode) // ERROR_BAD_PATHNAME
264 { 267 {
265 throw new WixException(WixErrors.FileNotFound(row.SourceLineNumbers, (string)row[i])); 268 throw new WixException(ErrorMessages.FileNotFound(row.SourceLineNumbers, (string)row[i]));
266 } 269 }
267 else 270 else
268 { 271 {
269 throw new WixException(WixErrors.Win32Exception(e.NativeErrorCode, e.Message)); 272 throw new WixException(ErrorMessages.Win32Exception(e.NativeErrorCode, e.Message));
270 } 273 }
271 } 274 }
272 } 275 }
@@ -279,7 +282,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
279 // check for a stream name that is more than 62 characters long (the maximum allowed length) 282 // check for a stream name that is more than 62 characters long (the maximum allowed length)
280 if (needStream && MsiInterop.MsiMaxStreamNameLength < streamName.Length) 283 if (needStream && MsiInterop.MsiMaxStreamNameLength < streamName.Length)
281 { 284 {
282 Messaging.Instance.OnMessage(WixErrors.StreamNameTooLong(row.SourceLineNumbers, table.Name, streamName.ToString(), streamName.Length)); 285 this.Messaging.Write(ErrorMessages.StreamNameTooLong(row.SourceLineNumbers, table.Name, streamName.ToString(), streamName.Length));
283 } 286 }
284 else // add the row to the database 287 else // add the row to the database
285 { 288 {
@@ -309,7 +312,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
309 // Bind the transform. 312 // Bind the transform.
310 this.BindTransform(subStorage.Data, transformFile); 313 this.BindTransform(subStorage.Data, transformFile);
311 314
312 if (Messaging.Instance.EncounteredError) 315 if (this.Messaging.EncounteredError)
313 { 316 {
314 continue; 317 continue;
315 } 318 }
@@ -338,7 +341,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
338 341
339 private void BindTransform(Output transform, string outputPath) 342 private void BindTransform(Output transform, string outputPath)
340 { 343 {
341 BindTransformCommand command = new BindTransformCommand(); 344 var command = new BindTransformCommand();
345 command.Messaging = this.Messaging;
342 command.Extensions = this.Extensions; 346 command.Extensions = this.Extensions;
343 command.TempFilesLocation = this.TempFilesLocation; 347 command.TempFilesLocation = this.TempFilesLocation;
344 command.Transform = transform; 348 command.Transform = transform;
@@ -372,7 +376,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
372 catch (WixInvalidIdtException) 376 catch (WixInvalidIdtException)
373 { 377 {
374 // the IDT should be valid, so an invalid code page was given 378 // the IDT should be valid, so an invalid code page was given
375 throw new WixException(WixErrors.IllegalCodepage(codepage)); 379 throw new WixException(ErrorMessages.IllegalCodepage(codepage));
376 } 380 }
377 } 381 }
378 } 382 }
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs
index 32a05d93..8d1edb41 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs
@@ -13,6 +13,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
13 using WixToolset.Data; 13 using WixToolset.Data;
14 using WixToolset.Data.WindowsInstaller; 14 using WixToolset.Data.WindowsInstaller;
15 using WixToolset.Data.WindowsInstaller.Rows; 15 using WixToolset.Data.WindowsInstaller.Rows;
16 using WixToolset.Extensibility.Services;
16 using WixToolset.MergeMod; 17 using WixToolset.MergeMod;
17 using WixToolset.Msi; 18 using WixToolset.Msi;
18 19
@@ -23,6 +24,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
23 { 24 {
24 public IEnumerable<FileFacade> FileFacades { private get; set; } 25 public IEnumerable<FileFacade> FileFacades { private get; set; }
25 26
27 public IMessaging Messaging { private get; set; }
28
26 public Output Output { private get; set; } 29 public Output Output { private get; set; }
27 30
28 public string OutputPath { private get; set; } 31 public string OutputPath { private get; set; }
@@ -73,11 +76,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
73 } 76 }
74 catch (FormatException) 77 catch (FormatException)
75 { 78 {
76 Messaging.Instance.OnMessage(WixErrors.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.Language)); 79 this.Messaging.Write(ErrorMessages.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.Language));
77 continue; 80 continue;
78 } 81 }
79 82
80 Messaging.Instance.OnMessage(WixVerboses.OpeningMergeModule(wixMergeRow.SourceFile, mergeLanguage)); 83 this.Messaging.Write(VerboseMessages.OpeningMergeModule(wixMergeRow.SourceFile, mergeLanguage));
81 merge.OpenModule(wixMergeRow.SourceFile, mergeLanguage); 84 merge.OpenModule(wixMergeRow.SourceFile, mergeLanguage);
82 moduleOpen = true; 85 moduleOpen = true;
83 86
@@ -89,7 +92,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
89 } 92 }
90 93
91 // merge the module into the database that's being built 94 // merge the module into the database that's being built
92 Messaging.Instance.OnMessage(WixVerboses.MergingMergeModule(wixMergeRow.SourceFile)); 95 this.Messaging.Write(VerboseMessages.MergingMergeModule(wixMergeRow.SourceFile));
93 merge.MergeEx(wixMergeRow.Feature, wixMergeRow.Directory, callback); 96 merge.MergeEx(wixMergeRow.Feature, wixMergeRow.Directory, callback);
94 97
95 // connect any non-primary features 98 // connect any non-primary features
@@ -99,7 +102,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
99 { 102 {
100 if (wixMergeRow.Id == (string)row[1]) 103 if (wixMergeRow.Id == (string)row[1])
101 { 104 {
102 Messaging.Instance.OnMessage(WixVerboses.ConnectingMergeModule(wixMergeRow.SourceFile, (string)row[0])); 105 this.Messaging.Write(VerboseMessages.ConnectingMergeModule(wixMergeRow.SourceFile, (string)row[0]));
103 merge.Connect((string)row[0]); 106 merge.Connect((string)row[0]);
104 } 107 }
105 } 108 }
@@ -144,38 +147,38 @@ namespace WixToolset.Core.WindowsInstaller.Bind
144 switch (mergeError.Type) 147 switch (mergeError.Type)
145 { 148 {
146 case MsmErrorType.msmErrorExclusion: 149 case MsmErrorType.msmErrorExclusion:
147 Messaging.Instance.OnMessage(WixErrors.MergeExcludedModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, moduleKeys.ToString())); 150 this.Messaging.Write(ErrorMessages.MergeExcludedModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, moduleKeys.ToString()));
148 break; 151 break;
149 case MsmErrorType.msmErrorFeatureRequired: 152 case MsmErrorType.msmErrorFeatureRequired:
150 Messaging.Instance.OnMessage(WixErrors.MergeFeatureRequired(wixMergeRow.SourceLineNumbers, mergeError.ModuleTable, moduleKeys.ToString(), wixMergeRow.SourceFile, wixMergeRow.Id)); 153 this.Messaging.Write(ErrorMessages.MergeFeatureRequired(wixMergeRow.SourceLineNumbers, mergeError.ModuleTable, moduleKeys.ToString(), wixMergeRow.SourceFile, wixMergeRow.Id));
151 break; 154 break;
152 case MsmErrorType.msmErrorLanguageFailed: 155 case MsmErrorType.msmErrorLanguageFailed:
153 Messaging.Instance.OnMessage(WixErrors.MergeLanguageFailed(wixMergeRow.SourceLineNumbers, mergeError.Language, wixMergeRow.SourceFile)); 156 this.Messaging.Write(ErrorMessages.MergeLanguageFailed(wixMergeRow.SourceLineNumbers, mergeError.Language, wixMergeRow.SourceFile));
154 break; 157 break;
155 case MsmErrorType.msmErrorLanguageUnsupported: 158 case MsmErrorType.msmErrorLanguageUnsupported:
156 Messaging.Instance.OnMessage(WixErrors.MergeLanguageUnsupported(wixMergeRow.SourceLineNumbers, mergeError.Language, wixMergeRow.SourceFile)); 159 this.Messaging.Write(ErrorMessages.MergeLanguageUnsupported(wixMergeRow.SourceLineNumbers, mergeError.Language, wixMergeRow.SourceFile));
157 break; 160 break;
158 case MsmErrorType.msmErrorResequenceMerge: 161 case MsmErrorType.msmErrorResequenceMerge:
159 Messaging.Instance.OnMessage(WixWarnings.MergeRescheduledAction(wixMergeRow.SourceLineNumbers, mergeError.DatabaseTable, databaseKeys.ToString(), wixMergeRow.SourceFile)); 162 this.Messaging.Write(WarningMessages.MergeRescheduledAction(wixMergeRow.SourceLineNumbers, mergeError.DatabaseTable, databaseKeys.ToString(), wixMergeRow.SourceFile));
160 break; 163 break;
161 case MsmErrorType.msmErrorTableMerge: 164 case MsmErrorType.msmErrorTableMerge:
162 if ("_Validation" != mergeError.DatabaseTable) // ignore merge errors in the _Validation table 165 if ("_Validation" != mergeError.DatabaseTable) // ignore merge errors in the _Validation table
163 { 166 {
164 Messaging.Instance.OnMessage(WixWarnings.MergeTableFailed(wixMergeRow.SourceLineNumbers, mergeError.DatabaseTable, databaseKeys.ToString(), wixMergeRow.SourceFile)); 167 this.Messaging.Write(WarningMessages.MergeTableFailed(wixMergeRow.SourceLineNumbers, mergeError.DatabaseTable, databaseKeys.ToString(), wixMergeRow.SourceFile));
165 } 168 }
166 break; 169 break;
167 case MsmErrorType.msmErrorPlatformMismatch: 170 case MsmErrorType.msmErrorPlatformMismatch:
168 Messaging.Instance.OnMessage(WixErrors.MergePlatformMismatch(wixMergeRow.SourceLineNumbers, wixMergeRow.SourceFile)); 171 this.Messaging.Write(ErrorMessages.MergePlatformMismatch(wixMergeRow.SourceLineNumbers, wixMergeRow.SourceFile));
169 break; 172 break;
170 default: 173 default:
171 Messaging.Instance.OnMessage(WixErrors.UnexpectedException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedMergerErrorWithType, Enum.GetName(typeof(MsmErrorType), mergeError.Type), logPath), "InvalidOperationException", Environment.StackTrace)); 174 this.Messaging.Write(ErrorMessages.UnexpectedException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedMergerErrorWithType, Enum.GetName(typeof(MsmErrorType), mergeError.Type), logPath), "InvalidOperationException", Environment.StackTrace));
172 break; 175 break;
173 } 176 }
174 } 177 }
175 178
176 if (0 >= mergeErrors.Count && !commit) 179 if (0 >= mergeErrors.Count && !commit)
177 { 180 {
178 Messaging.Instance.OnMessage(WixErrors.UnexpectedException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedMergerErrorInSourceFile, wixMergeRow.SourceFile, logPath), "InvalidOperationException", Environment.StackTrace)); 181 this.Messaging.Write(ErrorMessages.UnexpectedException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedMergerErrorInSourceFile, wixMergeRow.SourceFile, logPath), "InvalidOperationException", Environment.StackTrace));
179 } 182 }
180 183
181 if (moduleOpen) 184 if (moduleOpen)
@@ -199,7 +202,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
199 } 202 }
200 203
201 // stop processing if an error previously occurred 204 // stop processing if an error previously occurred
202 if (Messaging.Instance.EncounteredError) 205 if (this.Messaging.EncounteredError)
203 { 206 {
204 return; 207 return;
205 } 208 }
@@ -223,7 +226,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
223 { 226 {
224 if (null != record) 227 if (null != record)
225 { 228 {
226 Messaging.Instance.OnMessage(WixWarnings.SuppressMergedAction((string)row[1], row[0].ToString())); 229 this.Messaging.Write(WarningMessages.SuppressMergedAction((string)row[1], row[0].ToString()));
227 view.Modify(ModifyView.Delete, record); 230 view.Modify(ModifyView.Delete, record);
228 } 231 }
229 } 232 }
@@ -251,7 +254,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
251 break; 254 break;
252 } 255 }
253 256
254 Messaging.Instance.OnMessage(WixWarnings.SuppressMergedAction(resultRecord.GetString(1), tableName)); 257 this.Messaging.Write(WarningMessages.SuppressMergedAction(resultRecord.GetString(1), tableName));
255 } 258 }
256 } 259 }
257 } 260 }
@@ -273,7 +276,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
273 } 276 }
274 277
275 // now update the Attributes column for the files from the Merge Modules 278 // now update the Attributes column for the files from the Merge Modules
276 Messaging.Instance.OnMessage(WixVerboses.ResequencingMergeModuleFiles()); 279 this.Messaging.Write(VerboseMessages.ResequencingMergeModuleFiles());
277 using (View view = db.OpenView("SELECT `Sequence`, `Attributes` FROM `File` WHERE `File`=?")) 280 using (View view = db.OpenView("SELECT `Sequence`, `Attributes` FROM `File` WHERE `File`=?"))
278 { 281 {
279 foreach (var file in this.FileFacades) 282 foreach (var file in this.FileFacades)
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs
index aa4382f5..e1a26a67 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs
@@ -97,7 +97,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
97 { 97 {
98 if (null == fileRecord) 98 if (null == fileRecord)
99 { 99 {
100 throw new WixException(WixErrors.FileIdentifierNotFound(facade.File.SourceLineNumbers, facade.File.File)); 100 throw new WixException(ErrorMessages.FileIdentifierNotFound(facade.File.SourceLineNumbers, facade.File.File));
101 } 101 }
102 102
103 relativeFileLayoutPath = Binder.GetFileSourcePath(directories, fileRecord[1], fileRecord[2], this.Compressed, this.LongNamesInImage); 103 relativeFileLayoutPath = Binder.GetFileSourcePath(directories, fileRecord[1], fileRecord[2], this.Compressed, this.LongNamesInImage);
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs
index cf9c0332..47eb9408 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs
@@ -9,6 +9,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
9 using WixToolset.Core.Native; 9 using WixToolset.Core.Native;
10 using WixToolset.Data; 10 using WixToolset.Data;
11 using WixToolset.Data.Tuples; 11 using WixToolset.Data.Tuples;
12 using WixToolset.Extensibility.Services;
12 13
13 internal class SequenceActionsCommand 14 internal class SequenceActionsCommand
14 { 15 {
@@ -27,7 +28,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
27 28
28 private Dictionary<string, WixActionTuple> StandardActionsById { get; } 29 private Dictionary<string, WixActionTuple> StandardActionsById { get; }
29 30
30 public Messaging Messaging { private get; set; } 31 public IMessaging Messaging { private get; set; }
31 32
32 public void Execute() 33 public void Execute()
33 { 34 {
@@ -64,10 +65,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
64 { 65 {
65 if (overridableActionRows.TryGetValue(actionRow.Id.Id, out var collidingActionRow)) 66 if (overridableActionRows.TryGetValue(actionRow.Id.Id, out var collidingActionRow))
66 { 67 {
67 this.Messaging.OnMessage(WixErrors.OverridableActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); 68 this.Messaging.Write(ErrorMessages.OverridableActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
68 if (null != collidingActionRow.SourceLineNumbers) 69 if (null != collidingActionRow.SourceLineNumbers)
69 { 70 {
70 this.Messaging.OnMessage(WixErrors.OverridableActionCollision2(collidingActionRow.SourceLineNumbers)); 71 this.Messaging.Write(ErrorMessages.OverridableActionCollision2(collidingActionRow.SourceLineNumbers));
71 } 72 }
72 } 73 }
73 else 74 else
@@ -93,10 +94,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
93 94
94 if (overridableActionRows.TryGetValue(actionRow.Id.Id, out var collidingActionRow)) 95 if (overridableActionRows.TryGetValue(actionRow.Id.Id, out var collidingActionRow))
95 { 96 {
96 this.Messaging.OnMessage(WixErrors.ActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); 97 this.Messaging.Write(ErrorMessages.ActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
97 if (null != collidingActionRow.SourceLineNumbers) 98 if (null != collidingActionRow.SourceLineNumbers)
98 { 99 {
99 this.Messaging.OnMessage(WixErrors.ActionCollision2(collidingActionRow.SourceLineNumbers)); 100 this.Messaging.Write(ErrorMessages.ActionCollision2(collidingActionRow.SourceLineNumbers));
100 } 101 }
101 } 102 }
102 else 103 else
@@ -127,20 +128,20 @@ namespace WixToolset.Core.WindowsInstaller.Bind
127 { 128 {
128 if (requiredActionRow.Overridable) 129 if (requiredActionRow.Overridable)
129 { 130 {
130 this.Messaging.OnMessage(WixWarnings.SuppressAction(suppressActionRow.SourceLineNumbers, suppressActionRow.Action, suppressActionRow.SequenceTable.ToString())); 131 this.Messaging.Write(WarningMessages.SuppressAction(suppressActionRow.SourceLineNumbers, suppressActionRow.Action, suppressActionRow.SequenceTable.ToString()));
131 if (null != requiredActionRow.SourceLineNumbers) 132 if (null != requiredActionRow.SourceLineNumbers)
132 { 133 {
133 this.Messaging.OnMessage(WixWarnings.SuppressAction2(requiredActionRow.SourceLineNumbers)); 134 this.Messaging.Write(WarningMessages.SuppressAction2(requiredActionRow.SourceLineNumbers));
134 } 135 }
135 136
136 requiredActionRows.Remove(key); 137 requiredActionRows.Remove(key);
137 } 138 }
138 else // suppressing a non-overridable action row 139 else // suppressing a non-overridable action row
139 { 140 {
140 this.Messaging.OnMessage(WixErrors.SuppressNonoverridableAction(suppressActionRow.SourceLineNumbers, suppressActionRow.SequenceTable.ToString(), suppressActionRow.Action)); 141 this.Messaging.Write(ErrorMessages.SuppressNonoverridableAction(suppressActionRow.SourceLineNumbers, suppressActionRow.SequenceTable.ToString(), suppressActionRow.Action));
141 if (null != requiredActionRow.SourceLineNumbers) 142 if (null != requiredActionRow.SourceLineNumbers)
142 { 143 {
143 this.Messaging.OnMessage(WixErrors.SuppressNonoverridableAction2(requiredActionRow.SourceLineNumbers)); 144 this.Messaging.Write(ErrorMessages.SuppressNonoverridableAction2(requiredActionRow.SourceLineNumbers));
144 } 145 }
145 } 146 }
146 } 147 }
@@ -156,14 +157,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
156 // check for standard actions that don't have a sequence number in a merge module 157 // check for standard actions that don't have a sequence number in a merge module
157 if (SectionType.Module == this.Section.Type && WindowsInstallerStandard.IsStandardAction(actionRow.Action)) 158 if (SectionType.Module == this.Section.Type && WindowsInstallerStandard.IsStandardAction(actionRow.Action))
158 { 159 {
159 this.Messaging.OnMessage(WixErrors.StandardActionRelativelyScheduledInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); 160 this.Messaging.Write(ErrorMessages.StandardActionRelativelyScheduledInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
160 } 161 }
161 162
162 this.SequenceActionRow(actionRow, requiredActionRows); 163 this.SequenceActionRow(actionRow, requiredActionRows);
163 } 164 }
164 else if (SectionType.Module == this.Section.Type && 0 < actionRow.Sequence && !WindowsInstallerStandard.IsStandardAction(actionRow.Action)) // check for custom actions and dialogs that have a sequence number 165 else if (SectionType.Module == this.Section.Type && 0 < actionRow.Sequence && !WindowsInstallerStandard.IsStandardAction(actionRow.Action)) // check for custom actions and dialogs that have a sequence number
165 { 166 {
166 this.Messaging.OnMessage(WixErrors.CustomActionSequencedInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); 167 this.Messaging.Write(ErrorMessages.CustomActionSequencedInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action));
167 } 168 }
168 } 169 }
169 170
@@ -231,10 +232,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
231 { 232 {
232 if (sequenceScheduledActionRow.Sequence == actionRow.Sequence) 233 if (sequenceScheduledActionRow.Sequence == actionRow.Sequence)
233 { 234 {
234 this.Messaging.OnMessage(WixWarnings.ActionSequenceCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, sequenceScheduledActionRow.Action, actionRow.Sequence)); 235 this.Messaging.Write(WarningMessages.ActionSequenceCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, sequenceScheduledActionRow.Action, actionRow.Sequence));
235 if (null != sequenceScheduledActionRow.SourceLineNumbers) 236 if (null != sequenceScheduledActionRow.SourceLineNumbers)
236 { 237 {
237 this.Messaging.OnMessage(WixWarnings.ActionSequenceCollision2(sequenceScheduledActionRow.SourceLineNumbers)); 238 this.Messaging.Write(WarningMessages.ActionSequenceCollision2(sequenceScheduledActionRow.SourceLineNumbers));
238 } 239 }
239 } 240 }
240 } 241 }
@@ -262,19 +263,19 @@ namespace WixToolset.Core.WindowsInstaller.Bind
262 // Create errors for all the before actions. 263 // Create errors for all the before actions.
263 foreach (var actionRow in relativeActions.PreviousActions) 264 foreach (var actionRow in relativeActions.PreviousActions)
264 { 265 {
265 this.Messaging.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action)); 266 this.Messaging.Write(ErrorMessages.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action));
266 } 267 }
267 268
268 // Create errors for all the after actions. 269 // Create errors for all the after actions.
269 foreach (var actionRow in relativeActions.NextActions) 270 foreach (var actionRow in relativeActions.NextActions)
270 { 271 {
271 this.Messaging.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action)); 272 this.Messaging.Write(ErrorMessages.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action));
272 } 273 }
273 274
274 // If there is source line information for the absolutely scheduled action display it 275 // If there is source line information for the absolutely scheduled action display it
275 if (absoluteActionRow.SourceLineNumbers != null) 276 if (absoluteActionRow.SourceLineNumbers != null)
276 { 277 {
277 this.Messaging.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction2(absoluteActionRow.SourceLineNumbers)); 278 this.Messaging.Write(ErrorMessages.ActionScheduledRelativeToTerminationAction2(absoluteActionRow.SourceLineNumbers));
278 } 279 }
279 280
280 continue; 281 continue;
@@ -289,10 +290,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
289 // look for collisions 290 // look for collisions
290 if (unusedSequence == previousUsedSequence) 291 if (unusedSequence == previousUsedSequence)
291 { 292 {
292 this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action)); 293 this.Messaging.Write(ErrorMessages.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action));
293 if (absoluteActionRow.SourceLineNumbers != null) 294 if (absoluteActionRow.SourceLineNumbers != null)
294 { 295 {
295 this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers)); 296 this.Messaging.Write(ErrorMessages.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers));
296 } 297 }
297 298
298 unusedSequence++; 299 unusedSequence++;
@@ -319,10 +320,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
319 320
320 if (unusedSequence == nextUsedSequence) 321 if (unusedSequence == nextUsedSequence)
321 { 322 {
322 this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action)); 323 this.Messaging.Write(ErrorMessages.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action));
323 if (absoluteActionRow.SourceLineNumbers != null) 324 if (absoluteActionRow.SourceLineNumbers != null)
324 { 325 {
325 this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers)); 326 this.Messaging.Write(ErrorMessages.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers));
326 } 327 }
327 328
328 unusedSequence--; 329 unusedSequence--;
@@ -596,7 +597,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
596 } 597 }
597 else if (actionRow == parentActionRow || this.ContainsChildActionRow(actionRow, parentActionRow)) // cycle detected 598 else if (actionRow == parentActionRow || this.ContainsChildActionRow(actionRow, parentActionRow)) // cycle detected
598 { 599 {
599 throw new WixException(WixErrors.ActionCircularDependency(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, parentActionRow.Action)); 600 throw new WixException(ErrorMessages.ActionCircularDependency(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, parentActionRow.Action));
600 } 601 }
601 602
602 // Add this action to the appropriate list of dependent action rows. 603 // Add this action to the appropriate list of dependent action rows.
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateControlTextCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateControlTextCommand.cs
index dddc9380..3ad2470f 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateControlTextCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateControlTextCommand.cs
@@ -7,9 +7,12 @@ namespace WixToolset.Core.WindowsInstaller.Bind
7 using WixToolset.Data; 7 using WixToolset.Data;
8 using WixToolset.Data.WindowsInstaller; 8 using WixToolset.Data.WindowsInstaller;
9 using WixToolset.Data.WindowsInstaller.Rows; 9 using WixToolset.Data.WindowsInstaller.Rows;
10 using WixToolset.Extensibility.Services;
10 11
11 internal class UpdateControlTextCommand 12 internal class UpdateControlTextCommand
12 { 13 {
14 public IMessaging Messaging { private get; set; }
15
13 public Table BBControlTable { private get; set; } 16 public Table BBControlTable { private get; set; }
14 17
15 public Table WixBBControlTable { private get; set; } 18 public Table WixBBControlTable { private get; set; }
@@ -60,19 +63,19 @@ namespace WixToolset.Core.WindowsInstaller.Bind
60 } 63 }
61 catch (DirectoryNotFoundException e) 64 catch (DirectoryNotFoundException e)
62 { 65 {
63 Messaging.Instance.OnMessage(WixErrors.BinderFileManagerMissingFile(sourceLineNumbers, e.Message)); 66 this.Messaging.Write(ErrorMessages.BinderFileManagerMissingFile(sourceLineNumbers, e.Message));
64 } 67 }
65 catch (FileNotFoundException e) 68 catch (FileNotFoundException e)
66 { 69 {
67 Messaging.Instance.OnMessage(WixErrors.BinderFileManagerMissingFile(sourceLineNumbers, e.Message)); 70 this.Messaging.Write(ErrorMessages.BinderFileManagerMissingFile(sourceLineNumbers, e.Message));
68 } 71 }
69 catch (IOException e) 72 catch (IOException e)
70 { 73 {
71 Messaging.Instance.OnMessage(WixErrors.BinderFileManagerMissingFile(sourceLineNumbers, e.Message)); 74 this.Messaging.Write(ErrorMessages.BinderFileManagerMissingFile(sourceLineNumbers, e.Message));
72 } 75 }
73 catch (NotSupportedException) 76 catch (NotSupportedException)
74 { 77 {
75 Messaging.Instance.OnMessage(WixErrors.FileNotFound(sourceLineNumbers, source)); 78 this.Messaging.Write(ErrorMessages.FileNotFound(sourceLineNumbers, source));
76 } 79 }
77 80
78 return text; 81 return text;
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs
index cf620e72..10eae8f8 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs
@@ -15,6 +15,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
15 using WixToolset.Data; 15 using WixToolset.Data;
16 using WixToolset.Data.Tuples; 16 using WixToolset.Data.Tuples;
17 using WixToolset.Data.WindowsInstaller; 17 using WixToolset.Data.WindowsInstaller;
18 using WixToolset.Extensibility.Services;
18 using WixToolset.Msi; 19 using WixToolset.Msi;
19 20
20 /// <summary> 21 /// <summary>
@@ -22,11 +23,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
22 /// </summary> 23 /// </summary>
23 internal class UpdateFileFacadesCommand 24 internal class UpdateFileFacadesCommand
24 { 25 {
25 public UpdateFileFacadesCommand(IntermediateSection section) 26 public UpdateFileFacadesCommand(IMessaging messaging, IntermediateSection section)
26 { 27 {
28 this.Messaging = messaging;
27 this.Section = section; 29 this.Section = section;
28 } 30 }
29 31
32 private IMessaging Messaging { get; }
33
30 private IntermediateSection Section { get; } 34 private IntermediateSection Section { get; }
31 35
32 public IEnumerable<FileFacade> FileFacades { private get; set; } 36 public IEnumerable<FileFacade> FileFacades { private get; set; }
@@ -62,23 +66,23 @@ namespace WixToolset.Core.WindowsInstaller.Bind
62 } 66 }
63 catch (ArgumentException) 67 catch (ArgumentException)
64 { 68 {
65 Messaging.Instance.OnMessage(WixDataErrors.InvalidFileName(file.File.SourceLineNumbers, file.WixFile.Source.Path)); 69 this.Messaging.Write(ErrorMessages.InvalidFileName(file.File.SourceLineNumbers, file.WixFile.Source.Path));
66 return; 70 return;
67 } 71 }
68 catch (PathTooLongException) 72 catch (PathTooLongException)
69 { 73 {
70 Messaging.Instance.OnMessage(WixDataErrors.InvalidFileName(file.File.SourceLineNumbers, file.WixFile.Source.Path)); 74 this.Messaging.Write(ErrorMessages.InvalidFileName(file.File.SourceLineNumbers, file.WixFile.Source.Path));
71 return; 75 return;
72 } 76 }
73 catch (NotSupportedException) 77 catch (NotSupportedException)
74 { 78 {
75 Messaging.Instance.OnMessage(WixDataErrors.InvalidFileName(file.File.SourceLineNumbers, file.WixFile.Source.Path)); 79 this.Messaging.Write(ErrorMessages.InvalidFileName(file.File.SourceLineNumbers, file.WixFile.Source.Path));
76 return; 80 return;
77 } 81 }
78 82
79 if (!fileInfo.Exists) 83 if (!fileInfo.Exists)
80 { 84 {
81 Messaging.Instance.OnMessage(WixErrors.CannotFindFile(file.File.SourceLineNumbers, file.File.File, file.File.LongFileName, file.WixFile.Source.Path)); 85 this.Messaging.Write(ErrorMessages.CannotFindFile(file.File.SourceLineNumbers, file.File.File, file.File.LongFileName, file.WixFile.Source.Path));
82 return; 86 return;
83 } 87 }
84 88
@@ -86,7 +90,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
86 { 90 {
87 if (Int32.MaxValue < fileStream.Length) 91 if (Int32.MaxValue < fileStream.Length)
88 { 92 {
89 throw new WixException(WixErrors.FileTooLarge(file.File.SourceLineNumbers, file.WixFile.Source.Path)); 93 throw new WixException(ErrorMessages.FileTooLarge(file.File.SourceLineNumbers, file.WixFile.Source.Path));
90 } 94 }
91 95
92 file.File.FileSize = Convert.ToInt32(fileStream.Length, CultureInfo.InvariantCulture); 96 file.File.FileSize = Convert.ToInt32(fileStream.Length, CultureInfo.InvariantCulture);
@@ -102,11 +106,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
102 { 106 {
103 if (0x2 == e.NativeErrorCode) // ERROR_FILE_NOT_FOUND 107 if (0x2 == e.NativeErrorCode) // ERROR_FILE_NOT_FOUND
104 { 108 {
105 throw new WixException(WixErrors.FileNotFound(file.File.SourceLineNumbers, fileInfo.FullName)); 109 throw new WixException(ErrorMessages.FileNotFound(file.File.SourceLineNumbers, fileInfo.FullName));
106 } 110 }
107 else 111 else
108 { 112 {
109 throw new WixException(WixErrors.Win32Exception(e.NativeErrorCode, e.Message)); 113 throw new WixException(ErrorMessages.Win32Exception(e.NativeErrorCode, e.Message));
110 } 114 }
111 } 115 }
112 116
@@ -128,14 +132,14 @@ namespace WixToolset.Core.WindowsInstaller.Bind
128 // for unversioned file. That's allowed but generally a dangerous thing to do so let's point that out to the user. 132 // for unversioned file. That's allowed but generally a dangerous thing to do so let's point that out to the user.
129 if (!this.FileFacades.Any(r => file.File.Version.Equals(r.File.File, StringComparison.Ordinal))) 133 if (!this.FileFacades.Any(r => file.File.Version.Equals(r.File.File, StringComparison.Ordinal)))
130 { 134 {
131 Messaging.Instance.OnMessage(WixWarnings.DefaultVersionUsedForUnversionedFile(file.File.SourceLineNumbers, file.File.Version, file.File.File)); 135 this.Messaging.Write(WarningMessages.DefaultVersionUsedForUnversionedFile(file.File.SourceLineNumbers, file.File.Version, file.File.File));
132 } 136 }
133 } 137 }
134 else 138 else
135 { 139 {
136 if (null != file.File.Language) 140 if (null != file.File.Language)
137 { 141 {
138 Messaging.Instance.OnMessage(WixWarnings.DefaultLanguageUsedForUnversionedFile(file.File.SourceLineNumbers, file.File.Language, file.File.File)); 142 this.Messaging.Write(WarningMessages.DefaultLanguageUsedForUnversionedFile(file.File.SourceLineNumbers, file.File.Language, file.File.File));
139 } 143 }
140 144
141 int[] hash; 145 int[] hash;
@@ -147,11 +151,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
147 { 151 {
148 if (0x2 == e.NativeErrorCode) // ERROR_FILE_NOT_FOUND 152 if (0x2 == e.NativeErrorCode) // ERROR_FILE_NOT_FOUND
149 { 153 {
150 throw new WixException(WixErrors.FileNotFound(file.File.SourceLineNumbers, fileInfo.FullName)); 154 throw new WixException(ErrorMessages.FileNotFound(file.File.SourceLineNumbers, fileInfo.FullName));
151 } 155 }
152 else 156 else
153 { 157 {
154 throw new WixException(WixErrors.Win32Exception(e.NativeErrorCode, fileInfo.FullName, e.Message)); 158 throw new WixException(ErrorMessages.Win32Exception(e.NativeErrorCode, fileInfo.FullName, e.Message));
155 } 159 }
156 } 160 }
157 161
@@ -193,7 +197,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
193 197
194 if (!String.IsNullOrEmpty(file.File.Language) && String.IsNullOrEmpty(language)) 198 if (!String.IsNullOrEmpty(file.File.Language) && String.IsNullOrEmpty(language))
195 { 199 {
196 Messaging.Instance.OnMessage(WixWarnings.DefaultLanguageUsedForVersionedFile(file.File.SourceLineNumbers, file.File.Language, file.File.File)); 200 this.Messaging.Write(WarningMessages.DefaultLanguageUsedForVersionedFile(file.File.SourceLineNumbers, file.File.Language, file.File.File));
197 } 201 }
198 else // override the default provided by the user (usually nothing) with the actual language from the file itself. 202 else // override the default provided by the user (usually nothing) with the actual language from the file itself.
199 { 203 {
@@ -260,7 +264,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
260 } 264 }
261 else if (file.WixFile.File_AssemblyApplication == null) 265 else if (file.WixFile.File_AssemblyApplication == null)
262 { 266 {
263 throw new WixException(WixErrors.GacAssemblyNoStrongName(file.File.SourceLineNumbers, fileInfo.FullName, file.File.Component_)); 267 throw new WixException(ErrorMessages.GacAssemblyNoStrongName(file.File.SourceLineNumbers, fileInfo.FullName, file.File.Component_));
264 } 268 }
265 269
266 string assemblyVersion = referenceIdentity.GetAttribute(null, "Version"); 270 string assemblyVersion = referenceIdentity.GetAttribute(null, "Version");
@@ -271,7 +275,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
271 } 275 }
272 else 276 else
273 { 277 {
274 Messaging.Instance.OnMessage(WixErrors.InvalidAssemblyFile(file.File.SourceLineNumbers, fileInfo.FullName, String.Format(CultureInfo.InvariantCulture, "HRESULT: 0x{0:x8}", result))); 278 this.Messaging.Write(ErrorMessages.InvalidAssemblyFile(file.File.SourceLineNumbers, fileInfo.FullName, String.Format(CultureInfo.InvariantCulture, "HRESULT: 0x{0:x8}", result)));
275 return; 279 return;
276 } 280 }
277 281
@@ -360,7 +364,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
360 FileFacade fileManifest = this.FileFacades.SingleOrDefault(r => r.File.File.Equals(file.WixFile.File_AssemblyManifest, StringComparison.Ordinal)); 364 FileFacade fileManifest = this.FileFacades.SingleOrDefault(r => r.File.File.Equals(file.WixFile.File_AssemblyManifest, StringComparison.Ordinal));
361 if (null == fileManifest) 365 if (null == fileManifest)
362 { 366 {
363 Messaging.Instance.OnMessage(WixErrors.MissingManifestForWin32Assembly(file.File.SourceLineNumbers, file.File.File, file.WixFile.File_AssemblyManifest)); 367 this.Messaging.Write(ErrorMessages.MissingManifestForWin32Assembly(file.File.SourceLineNumbers, file.File.File, file.WixFile.File_AssemblyManifest));
364 } 368 }
365 369
366 string win32Type = null; 370 string win32Type = null;
@@ -397,7 +401,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
397 } 401 }
398 if (!hasNextSibling) 402 if (!hasNextSibling)
399 { 403 {
400 Messaging.Instance.OnMessage(WixErrors.InvalidManifestContent(file.File.SourceLineNumbers, fileManifest.WixFile.Source.Path)); 404 this.Messaging.Write(ErrorMessages.InvalidManifestContent(file.File.SourceLineNumbers, fileManifest.WixFile.Source.Path));
401 return; 405 return;
402 } 406 }
403 407
@@ -435,11 +439,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
435 } 439 }
436 catch (FileNotFoundException fe) 440 catch (FileNotFoundException fe)
437 { 441 {
438 Messaging.Instance.OnMessage(WixErrors.FileNotFound(new SourceLineNumber(fileManifest.WixFile.Source.Path), fe.FileName, "AssemblyManifest")); 442 this.Messaging.Write(ErrorMessages.FileNotFound(new SourceLineNumber(fileManifest.WixFile.Source.Path), fe.FileName, "AssemblyManifest"));
439 } 443 }
440 catch (XmlException xe) 444 catch (XmlException xe)
441 { 445 {
442 Messaging.Instance.OnMessage(WixErrors.InvalidXml(new SourceLineNumber(fileManifest.WixFile.Source.Path), "manifest", xe.Message)); 446 this.Messaging.Write(ErrorMessages.InvalidXml(new SourceLineNumber(fileManifest.WixFile.Source.Path), "manifest", xe.Message));
443 } 447 }
444 448
445 if (!String.IsNullOrEmpty(win32Name)) 449 if (!String.IsNullOrEmpty(win32Name))
@@ -482,7 +486,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
482 // check for null value (this can occur when grabbing the file version from an assembly without one) 486 // check for null value (this can occur when grabbing the file version from an assembly without one)
483 if (String.IsNullOrEmpty(value)) 487 if (String.IsNullOrEmpty(value))
484 { 488 {
485 Messaging.Instance.OnMessage(WixWarnings.NullMsiAssemblyNameValue(file.File.SourceLineNumbers, file.File.Component_, name)); 489 this.Messaging.Write(WarningMessages.NullMsiAssemblyNameValue(file.File.SourceLineNumbers, file.File.Component_, name));
486 } 490 }
487 else 491 else
488 { 492 {
@@ -491,7 +495,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
491 String.IsNullOrEmpty(file.WixFile.File_AssemblyApplication) && 495 String.IsNullOrEmpty(file.WixFile.File_AssemblyApplication) &&
492 !String.Equals(Path.GetFileNameWithoutExtension(file.File.LongFileName), value, StringComparison.OrdinalIgnoreCase)) 496 !String.Equals(Path.GetFileNameWithoutExtension(file.File.LongFileName), value, StringComparison.OrdinalIgnoreCase))
493 { 497 {
494 Messaging.Instance.OnMessage(WixErrors.GACAssemblyIdentityWarning(file.File.SourceLineNumbers, Path.GetFileNameWithoutExtension(file.File.LongFileName), value)); 498 this.Messaging.Write(ErrorMessages.GACAssemblyIdentityWarning(file.File.SourceLineNumbers, Path.GetFileNameWithoutExtension(file.File.LongFileName), value));
495 } 499 }
496 500
497 // override directly authored value 501 // override directly authored value
diff --git a/src/WixToolset.Core.WindowsInstaller/Data/Xsd/actions.xsd b/src/WixToolset.Core.WindowsInstaller/Data/Xsd/actions.xsd
new file mode 100644
index 00000000..bf0ccb95
--- /dev/null
+++ b/src/WixToolset.Core.WindowsInstaller/Data/Xsd/actions.xsd
@@ -0,0 +1,73 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3
4
5<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
6 targetNamespace="http://wixtoolset.org/schemas/v4/wi/actions"
7 xmlns="http://wixtoolset.org/schemas/v4/wi/actions">
8 <xs:annotation>
9 <xs:documentation>
10 Schema for describing standard actions in the Windows Installer.
11 </xs:documentation>
12 </xs:annotation>
13
14 <xs:element name="actions">
15 <xs:complexType>
16 <xs:sequence maxOccurs="unbounded">
17 <xs:element ref="action" />
18 </xs:sequence>
19 </xs:complexType>
20 </xs:element>
21
22 <xs:element name="action">
23 <xs:complexType>
24 <xs:attribute name="name" type="xs:string" use="required">
25 <xs:annotation>
26 <xs:documentation>Name of action</xs:documentation>
27 </xs:annotation>
28 </xs:attribute>
29 <xs:attribute name="condition" type="xs:string">
30 <xs:annotation>
31 <xs:documentation>Default condition for action</xs:documentation>
32 </xs:annotation>
33 </xs:attribute>
34 <xs:attribute name="sequence" type="xs:integer" use="required">
35 <xs:annotation>
36 <xs:documentation>Sequence of action</xs:documentation>
37 </xs:annotation>
38 </xs:attribute>
39 <xs:attribute name="AdminExecuteSequence" type="ActionsYesNoType">
40 <xs:annotation>
41 <xs:documentation>Specifies if action is allowed in AdminExecuteSequence</xs:documentation>
42 </xs:annotation>
43 </xs:attribute>
44 <xs:attribute name="AdminUISequence" type="ActionsYesNoType">
45 <xs:annotation>
46 <xs:documentation>Specifies if action is allowed in AdminUISequence</xs:documentation>
47 </xs:annotation>
48 </xs:attribute>
49 <xs:attribute name="AdvtExecuteSequence" type="ActionsYesNoType">
50 <xs:annotation>
51 <xs:documentation>Specifies if action is allowed in AdvtExecuteSequence</xs:documentation>
52 </xs:annotation>
53 </xs:attribute>
54 <xs:attribute name="InstallExecuteSequence" type="ActionsYesNoType">
55 <xs:annotation>
56 <xs:documentation>Specifies if action is allowed in InstallExecuteSequence</xs:documentation>
57 </xs:annotation>
58 </xs:attribute>
59 <xs:attribute name="InstallUISequence" type="ActionsYesNoType">
60 <xs:annotation>
61 <xs:documentation>Specifies if action is allowed in InstallUISequence</xs:documentation>
62 </xs:annotation>
63 </xs:attribute>
64 </xs:complexType>
65 </xs:element>
66
67 <xs:simpleType name="ActionsYesNoType">
68 <xs:restriction base="xs:NMTOKEN">
69 <xs:enumeration value="no" />
70 <xs:enumeration value="yes" />
71 </xs:restriction>
72 </xs:simpleType>
73</xs:schema>
diff --git a/src/WixToolset.Core.WindowsInstaller/Data/Xsd/tables.xsd b/src/WixToolset.Core.WindowsInstaller/Data/Xsd/tables.xsd
new file mode 100644
index 00000000..f87471bb
--- /dev/null
+++ b/src/WixToolset.Core.WindowsInstaller/Data/Xsd/tables.xsd
@@ -0,0 +1,248 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3
4
5<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
6 targetNamespace="http://wixtoolset.org/schemas/v4/wi/tables"
7 xmlns="http://wixtoolset.org/schemas/v4/wi/tables">
8 <xs:annotation>
9 <xs:documentation>
10 Schema for describing table definitions in Windows Installer.
11 </xs:documentation>
12 </xs:annotation>
13
14 <xs:element name="tableDefinitions">
15 <xs:complexType>
16 <xs:sequence maxOccurs="unbounded">
17 <xs:element ref="tableDefinition" />
18 </xs:sequence>
19 </xs:complexType>
20 </xs:element>
21
22 <xs:element name="tableDefinition">
23 <xs:complexType>
24 <xs:sequence maxOccurs="unbounded">
25 <xs:element ref="columnDefinition" />
26 </xs:sequence>
27 <xs:attribute name="createSymbols" type="TablesYesNoType">
28 <xs:annotation>
29 <xs:documentation>Boolean whether rows in this table create symbols</xs:documentation>
30 </xs:annotation>
31 </xs:attribute>
32 <xs:attribute name="name" type="NameType" use="required">
33 <xs:annotation>
34 <xs:documentation>Name of table in Windows Installer database</xs:documentation>
35 </xs:annotation>
36 </xs:attribute>
37 <xs:attribute name="unreal" type="TablesYesNoType">
38 <xs:annotation>
39 <xs:documentation>Specifies if table is virtual or not</xs:documentation>
40 </xs:annotation>
41 </xs:attribute>
42 <xs:attribute name="bootstrapperApplicationData" type="TablesYesNoType">
43 <xs:annotation>
44 <xs:documentation>Specifies if the table is a part of the Bootstrapper Application Data manifest</xs:documentation>
45 </xs:annotation>
46 </xs:attribute>
47 </xs:complexType>
48 </xs:element>
49
50 <xs:element name="columnDefinition">
51 <xs:complexType>
52 <xs:attribute name="name" type="NameType" use="required">
53 <xs:annotation>
54 <xs:documentation>Name of column in Windows Installer table</xs:documentation>
55 </xs:annotation>
56 </xs:attribute>
57
58 <xs:attribute name="added" type="TablesYesNoType">
59 <xs:annotation>
60 <xs:documentation>Whether this column was added by a transform.</xs:documentation>
61 </xs:annotation>
62 </xs:attribute>
63
64 <xs:attribute name="type" type="ColumnDefinitionType" use="required">
65 <xs:annotation>
66 <xs:documentation>Type of column in Windows Installer table</xs:documentation>
67 </xs:annotation>
68 </xs:attribute>
69
70 <xs:attribute name="length" use="required">
71 <xs:annotation>
72 <xs:documentation>Type of column in Windows Installer table</xs:documentation>
73 </xs:annotation>
74 <xs:simpleType>
75 <xs:restriction base="xs:integer">
76 <xs:minInclusive value="0" />
77 <xs:maxInclusive value="255" />
78 </xs:restriction>
79 </xs:simpleType>
80 </xs:attribute>
81
82 <xs:attribute name="primaryKey" type="TablesYesNoType">
83 <xs:annotation>
84 <xs:documentation>Boolean whether column is primary key of Windows Installer table</xs:documentation>
85 </xs:annotation>
86 </xs:attribute>
87
88 <xs:attribute name="nullable" type="TablesYesNoType">
89 <xs:annotation>
90 <xs:documentation>Boolean whether column is nullable in Windows Installer table</xs:documentation>
91 </xs:annotation>
92 </xs:attribute>
93
94 <xs:attribute name="unreal" type="TablesYesNoType">
95 <xs:annotation>
96 <xs:documentation>Boolean whether column is virtual in Windows Installer table</xs:documentation>
97 </xs:annotation>
98 </xs:attribute>
99
100 <xs:attribute name="modularize" type="TablesModularizeType">
101 <xs:annotation>
102 <xs:documentation>Enumeration specifying how column should have the ModuleId appended</xs:documentation>
103 </xs:annotation>
104 </xs:attribute>
105
106 <xs:attribute name="localizable" type="TablesYesNoType">
107 <xs:annotation>
108 <xs:documentation>Set to "yes" in order to allow substitution for localized variables.</xs:documentation>
109 </xs:annotation>
110 </xs:attribute>
111
112 <xs:attribute name="minValue" type="xs:long">
113 <xs:annotation>
114 <xs:documentation>Minimum value for column in Windows Installer table</xs:documentation>
115 </xs:annotation>
116 </xs:attribute>
117
118 <xs:attribute name="maxValue" type="xs:long">
119 <xs:annotation>
120 <xs:documentation>Maximum value for column in Windows Installer table</xs:documentation>
121 </xs:annotation>
122 </xs:attribute>
123
124 <xs:attribute name="keyTable" type="NameType">
125 <xs:annotation>
126 <xs:documentation>Foreign key table for column in Windows Installer table</xs:documentation>
127 </xs:annotation>
128 </xs:attribute>
129
130 <xs:attribute name="keyColumn">
131 <xs:annotation>
132 <xs:documentation>Maximum value for column in Windows Installer table</xs:documentation>
133 </xs:annotation>
134 <xs:simpleType>
135 <xs:restriction base="xs:integer">
136 <xs:minInclusive value="1" />
137 <xs:maxInclusive value="32" />
138 </xs:restriction>
139 </xs:simpleType>
140 </xs:attribute>
141
142 <xs:attribute name="category" type="TablesCategoryType">
143 <xs:annotation>
144 <xs:documentation>Specific column data types for column</xs:documentation>
145 </xs:annotation>
146 </xs:attribute>
147
148 <xs:attribute name="set" type="TablesSetType">
149 <xs:annotation>
150 <xs:documentation>List of permissible values for the column</xs:documentation>
151 </xs:annotation>
152 </xs:attribute>
153
154 <xs:attribute name="description" type="xs:string">
155 <xs:annotation>
156 <xs:documentation>Description of column</xs:documentation>
157 </xs:annotation>
158 </xs:attribute>
159
160 <xs:attribute name="escapeIdtCharacters" type="TablesYesNoType">
161 <xs:annotation>
162 <xs:documentation>Set to "yes" in order to make the idt exporter escape whitespace characters \r, \n, and \t.</xs:documentation>
163 </xs:annotation>
164 </xs:attribute>
165
166 <xs:attribute name="useCData" type="TablesYesNoType">
167 <xs:annotation>
168 <xs:documentation>Set to "yes" in order to make the Intermediate and Output objects wrap their data in a CDATA element to preserve whitespace.</xs:documentation>
169 </xs:annotation>
170 </xs:attribute>
171 </xs:complexType>
172 </xs:element>
173
174 <xs:simpleType name="NameType">
175 <xs:restriction base="xs:string">
176 <xs:minLength value="1" />
177 <xs:maxLength value="64" />
178 </xs:restriction>
179 </xs:simpleType>
180
181 <xs:simpleType name="ColumnDefinitionType">
182 <xs:restriction base="xs:NMTOKEN">
183 <xs:enumeration value="string" />
184 <xs:enumeration value="localized" />
185 <xs:enumeration value="number" />
186 <xs:enumeration value="object" />
187 <xs:enumeration value="preserved" />
188 </xs:restriction>
189 </xs:simpleType>
190
191 <xs:simpleType name="TablesYesNoType">
192 <xs:restriction base="xs:NMTOKEN">
193 <xs:enumeration value="yes" />
194 <xs:enumeration value="no" />
195 </xs:restriction>
196 </xs:simpleType>
197
198 <xs:simpleType name="TablesModularizeType">
199 <xs:restriction base="xs:NMTOKEN">
200 <xs:enumeration value="column" />
201 <xs:enumeration value="companionFile" />
202 <xs:enumeration value="condition" />
203 <xs:enumeration value="controlEventArgument" />
204 <xs:enumeration value="controlText" />
205 <xs:enumeration value="icon" />
206 <xs:enumeration value="none" />
207 <xs:enumeration value="property" />
208 <xs:enumeration value="semicolonDelimited" />
209 </xs:restriction>
210 </xs:simpleType>
211
212 <xs:simpleType name="TablesCategoryType">
213 <xs:restriction base="xs:NMTOKEN">
214 <xs:enumeration value="text" />
215 <xs:enumeration value="upperCase" />
216 <xs:enumeration value="lowerCase" />
217 <xs:enumeration value="integer" />
218 <xs:enumeration value="doubleInteger" />
219 <xs:enumeration value="timeDate" />
220 <xs:enumeration value="identifier" />
221 <xs:enumeration value="property" />
222 <xs:enumeration value="filename" />
223 <xs:enumeration value="wildCardFilename" />
224 <xs:enumeration value="path" />
225 <xs:enumeration value="paths" />
226 <xs:enumeration value="anyPath" />
227 <xs:enumeration value="defaultDir" />
228 <xs:enumeration value="regPath" />
229 <xs:enumeration value="formatted" />
230 <xs:enumeration value="formattedSddl" />
231 <xs:enumeration value="template" />
232 <xs:enumeration value="condition" />
233 <xs:enumeration value="guid" />
234 <xs:enumeration value="version" />
235 <xs:enumeration value="language" />
236 <xs:enumeration value="binary" />
237 <xs:enumeration value="customSource" />
238 <xs:enumeration value="cabinet" />
239 <xs:enumeration value="shortcut" />
240 </xs:restriction>
241 </xs:simpleType>
242
243 <xs:simpleType name="TablesSetType">
244 <xs:restriction base="xs:string">
245 <xs:pattern value="\w+(;\w+)*" />
246 </xs:restriction>
247 </xs:simpleType>
248</xs:schema>
diff --git a/src/WixToolset.Core.WindowsInstaller/Differ.cs b/src/WixToolset.Core.WindowsInstaller/Differ.cs
index 9bbde302..7cc204f9 100644
--- a/src/WixToolset.Core.WindowsInstaller/Differ.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Differ.cs
@@ -10,26 +10,29 @@ namespace WixToolset.Core.WindowsInstaller
10 using WixToolset.Data.WindowsInstaller; 10 using WixToolset.Data.WindowsInstaller;
11 using WixToolset.Data.WindowsInstaller.Rows; 11 using WixToolset.Data.WindowsInstaller.Rows;
12 using WixToolset.Extensibility; 12 using WixToolset.Extensibility;
13 using WixToolset.Extensibility.Services;
13 using WixToolset.Msi; 14 using WixToolset.Msi;
14 15
15 /// <summary> 16 /// <summary>
16 /// Creates a transform by diffing two outputs. 17 /// Creates a transform by diffing two outputs.
17 /// </summary> 18 /// </summary>
18 public sealed class Differ : IMessageHandler 19 public sealed class Differ
19 { 20 {
20 private List<IInspectorExtension> inspectorExtensions; 21 private List<IInspectorExtension> inspectorExtensions;
21 private bool showPedanticMessages; 22 private bool showPedanticMessages;
22 private bool suppressKeepingSpecialRows; 23 private bool suppressKeepingSpecialRows;
23 private bool preserveUnchangedRows; 24 private bool preserveUnchangedRows;
24 private const char sectionDelimiter = '/'; 25 private const char sectionDelimiter = '/';
26 private readonly IMessaging messaging;
25 private SummaryInformationStreams transformSummaryInfo; 27 private SummaryInformationStreams transformSummaryInfo;
26 28
27 /// <summary> 29 /// <summary>
28 /// Instantiates a new Differ class. 30 /// Instantiates a new Differ class.
29 /// </summary> 31 /// </summary>
30 public Differ() 32 public Differ(IMessaging messaging)
31 { 33 {
32 this.inspectorExtensions = new List<IInspectorExtension>(); 34 this.inspectorExtensions = new List<IInspectorExtension>();
35 this.messaging = messaging;
33 } 36 }
34 37
35 /// <summary> 38 /// <summary>
@@ -99,17 +102,17 @@ namespace WixToolset.Core.WindowsInstaller
99 // compare the codepages 102 // compare the codepages
100 if (targetOutput.Codepage != updatedOutput.Codepage && 0 == (TransformFlags.ErrorChangeCodePage & validationFlags)) 103 if (targetOutput.Codepage != updatedOutput.Codepage && 0 == (TransformFlags.ErrorChangeCodePage & validationFlags))
101 { 104 {
102 this.OnMessage(WixErrors.OutputCodepageMismatch(targetOutput.SourceLineNumbers, targetOutput.Codepage, updatedOutput.Codepage)); 105 this.messaging.Write(ErrorMessages.OutputCodepageMismatch(targetOutput.SourceLineNumbers, targetOutput.Codepage, updatedOutput.Codepage));
103 if (null != updatedOutput.SourceLineNumbers) 106 if (null != updatedOutput.SourceLineNumbers)
104 { 107 {
105 this.OnMessage(WixErrors.OutputCodepageMismatch2(updatedOutput.SourceLineNumbers)); 108 this.messaging.Write(ErrorMessages.OutputCodepageMismatch2(updatedOutput.SourceLineNumbers));
106 } 109 }
107 } 110 }
108 111
109 // compare the output types 112 // compare the output types
110 if (targetOutput.Type != updatedOutput.Type) 113 if (targetOutput.Type != updatedOutput.Type)
111 { 114 {
112 throw new WixException(WixErrors.OutputTypeMismatch(targetOutput.SourceLineNumbers, targetOutput.Type.ToString(), updatedOutput.Type.ToString())); 115 throw new WixException(ErrorMessages.OutputTypeMismatch(targetOutput.SourceLineNumbers, targetOutput.Type.ToString(), updatedOutput.Type.ToString()));
113 } 116 }
114 117
115 // compare the contents of the tables 118 // compare the contents of the tables
@@ -160,15 +163,6 @@ namespace WixToolset.Core.WindowsInstaller
160 } 163 }
161 164
162 /// <summary> 165 /// <summary>
163 /// Sends a message to the message delegate if there is one.
164 /// </summary>
165 /// <param name="mea">Message event arguments.</param>
166 public void OnMessage(MessageEventArgs e)
167 {
168 Messaging.Instance.OnMessage(e);
169 }
170
171 /// <summary>
172 /// Add a row to the <paramref name="index"/> using the primary key. 166 /// Add a row to the <paramref name="index"/> using the primary key.
173 /// </summary> 167 /// </summary>
174 /// <param name="index">The indexed rows.</param> 168 /// <param name="index">The indexed rows.</param>
@@ -210,7 +204,7 @@ namespace WixToolset.Core.WindowsInstaller
210 } 204 }
211 else if (this.showPedanticMessages) 205 else if (this.showPedanticMessages)
212 { 206 {
213 this.OnMessage(WixWarnings.DuplicatePrimaryKey(row.SourceLineNumbers, primaryKey, row.Table.Name)); 207 this.messaging.Write(ErrorMessages.DuplicatePrimaryKey(row.SourceLineNumbers, primaryKey, row.Table.Name));
214 } 208 }
215 } 209 }
216 else // use the string representation of the row as its primary key (it may not be unique) 210 else // use the string representation of the row as its primary key (it may not be unique)
@@ -370,7 +364,7 @@ namespace WixToolset.Core.WindowsInstaller
370 if (0 != targetTable.Definition.CompareTo(updatedTable.Definition)) 364 if (0 != targetTable.Definition.CompareTo(updatedTable.Definition))
371 { 365 {
372 // continue to the next table; may be more mismatches 366 // continue to the next table; may be more mismatches
373 this.OnMessage(WixErrors.DatabaseSchemaMismatch(targetOutput.SourceLineNumbers, targetTable.Name)); 367 this.messaging.Write(ErrorMessages.DatabaseSchemaMismatch(targetOutput.SourceLineNumbers, targetTable.Name));
374 } 368 }
375 else 369 else
376 { 370 {
@@ -425,7 +419,7 @@ namespace WixToolset.Core.WindowsInstaller
425 this.transformSummaryInfo.TargetProductCode = (string)row[1]; 419 this.transformSummaryInfo.TargetProductCode = (string)row[1];
426 if ("*" == this.transformSummaryInfo.TargetProductCode) 420 if ("*" == this.transformSummaryInfo.TargetProductCode)
427 { 421 {
428 this.OnMessage(WixErrors.ProductCodeInvalidForTransform(row.SourceLineNumbers)); 422 this.messaging.Write(ErrorMessages.ProductCodeInvalidForTransform(row.SourceLineNumbers));
429 } 423 }
430 } 424 }
431 else if ("ProductVersion" == (string)row[0]) 425 else if ("ProductVersion" == (string)row[0])
@@ -466,7 +460,7 @@ namespace WixToolset.Core.WindowsInstaller
466 this.transformSummaryInfo.UpdatedProductCode = (string)row[1]; 460 this.transformSummaryInfo.UpdatedProductCode = (string)row[1];
467 if ("*" == this.transformSummaryInfo.UpdatedProductCode) 461 if ("*" == this.transformSummaryInfo.UpdatedProductCode)
468 { 462 {
469 this.OnMessage(WixErrors.ProductCodeInvalidForTransform(row.SourceLineNumbers)); 463 this.messaging.Write(ErrorMessages.ProductCodeInvalidForTransform(row.SourceLineNumbers));
470 } 464 }
471 } 465 }
472 else if ("ProductVersion" == (string)row[0]) 466 else if ("ProductVersion" == (string)row[0])
diff --git a/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs b/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs
index 5c56d9aa..93dd9d3b 100644
--- a/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs
@@ -36,7 +36,7 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe
36 FileAttributes attributes = File.GetAttributes(this.Context.InputFilePath); 36 FileAttributes attributes = File.GetAttributes(this.Context.InputFilePath);
37 if (FileAttributes.ReadOnly == (attributes & FileAttributes.ReadOnly)) 37 if (FileAttributes.ReadOnly == (attributes & FileAttributes.ReadOnly))
38 { 38 {
39 this.Context.Messaging.OnMessage(WixErrors.ReadOnlyOutputFile(this.Context.InputFilePath)); 39 this.Context.Messaging.Write(ErrorMessages.ReadOnlyOutputFile(this.Context.InputFilePath));
40 return shouldCommit; 40 return shouldCommit;
41 } 41 }
42 42
@@ -179,7 +179,7 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe
179 // If the cabs aren't there, throw an error but continue to catch the other errors 179 // If the cabs aren't there, throw an error but continue to catch the other errors
180 if (!File.Exists(cabPath)) 180 if (!File.Exists(cabPath))
181 { 181 {
182 this.Context.Messaging.OnMessage(WixErrors.WixFileNotFound(cabPath)); 182 this.Context.Messaging.Write(ErrorMessages.WixFileNotFound(cabPath));
183 continue; 183 continue;
184 } 184 }
185 185
@@ -205,11 +205,11 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe
205 if ((5 == Environment.OSVersion.Version.Major && 2 == Environment.OSVersion.Version.Minor) || // W2K3 205 if ((5 == Environment.OSVersion.Version.Major && 2 == Environment.OSVersion.Version.Minor) || // W2K3
206 (5 == Environment.OSVersion.Version.Major && 1 == Environment.OSVersion.Version.Minor)) // XP 206 (5 == Environment.OSVersion.Version.Major && 1 == Environment.OSVersion.Version.Minor)) // XP
207 { 207 {
208 this.Context.Messaging.OnMessage(WixErrors.UnableToGetAuthenticodeCertOfFileDownlevelOS(cabPath, String.Format(CultureInfo.InvariantCulture, "HRESULT: 0x{0:x8}", HResult))); 208 this.Context.Messaging.Write(ErrorMessages.UnableToGetAuthenticodeCertOfFileDownlevelOS(cabPath, String.Format(CultureInfo.InvariantCulture, "HRESULT: 0x{0:x8}", HResult)));
209 } 209 }
210 else // otherwise, generic error 210 else // otherwise, generic error
211 { 211 {
212 this.Context.Messaging.OnMessage(WixErrors.UnableToGetAuthenticodeCertOfFile(cabPath, String.Format(CultureInfo.InvariantCulture, "HRESULT: 0x{0:x8}", HResult))); 212 this.Context.Messaging.Write(ErrorMessages.UnableToGetAuthenticodeCertOfFile(cabPath, String.Format(CultureInfo.InvariantCulture, "HRESULT: 0x{0:x8}", HResult)));
213 } 213 }
214 } 214 }
215 215
@@ -252,7 +252,7 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe
252 252
253 if (digitalCertificateTable.Rows.Count > 0) 253 if (digitalCertificateTable.Rows.Count > 0)
254 { 254 {
255 var command = new CreateIdtFileCommand(digitalCertificateTable, codepage, this.Context.IntermediateFolder, true); 255 var command = new CreateIdtFileCommand(this.Context.Messaging, digitalCertificateTable, codepage, this.Context.IntermediateFolder, true);
256 command.Execute(); 256 command.Execute();
257 257
258 database.Import(command.IdtPath); 258 database.Import(command.IdtPath);
@@ -261,7 +261,7 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe
261 261
262 if (digitalSignatureTable.Rows.Count > 0) 262 if (digitalSignatureTable.Rows.Count > 0)
263 { 263 {
264 var command = new CreateIdtFileCommand(digitalSignatureTable, codepage, this.Context.IntermediateFolder, true); 264 var command = new CreateIdtFileCommand(this.Context.Messaging, digitalSignatureTable, codepage, this.Context.IntermediateFolder, true);
265 command.Execute(); 265 command.Execute();
266 266
267 database.Import(command.IdtPath); 267 database.Import(command.IdtPath);
@@ -275,7 +275,7 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe
275 // If we did find external cabs but none of them were signed, give a warning 275 // If we did find external cabs but none of them were signed, give a warning
276 if (foundUnsignedExternals) 276 if (foundUnsignedExternals)
277 { 277 {
278 this.Context.Messaging.OnMessage(WixWarnings.ExternalCabsAreNotSigned(this.Context.InputFilePath)); 278 this.Context.Messaging.Write(WarningMessages.ExternalCabsAreNotSigned(this.Context.InputFilePath));
279 } 279 }
280 280
281 if (shouldCommit) 281 if (shouldCommit)
diff --git a/src/WixToolset.Core.WindowsInstaller/MelterCore.cs b/src/WixToolset.Core.WindowsInstaller/MelterCore.cs
index 75d43619..034c9465 100644
--- a/src/WixToolset.Core.WindowsInstaller/MelterCore.cs
+++ b/src/WixToolset.Core.WindowsInstaller/MelterCore.cs
@@ -7,8 +7,9 @@ namespace WixToolset
7 /// <summary> 7 /// <summary>
8 /// Melts a Module Wix document into a ComponentGroup representation. 8 /// Melts a Module Wix document into a ComponentGroup representation.
9 /// </summary> 9 /// </summary>
10 public sealed class MelterCore : IMessageHandler 10 public sealed class MelterCore
11 { 11 {
12#if TODO_MELT
12 /// <summary> 13 /// <summary>
13 /// Gets whether the melter core encountered an error while processing. 14 /// Gets whether the melter core encountered an error while processing.
14 /// </summary> 15 /// </summary>
@@ -26,5 +27,6 @@ namespace WixToolset
26 { 27 {
27 Messaging.Instance.OnMessage(e); 28 Messaging.Instance.OnMessage(e);
28 } 29 }
30#endif
29 } 31 }
30} 32}
diff --git a/src/WixToolset.Core.WindowsInstaller/Msi/WixInvalidIdtException.cs b/src/WixToolset.Core.WindowsInstaller/Msi/WixInvalidIdtException.cs
index a603d5a7..589da648 100644
--- a/src/WixToolset.Core.WindowsInstaller/Msi/WixInvalidIdtException.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Msi/WixInvalidIdtException.cs
@@ -16,7 +16,7 @@ namespace WixToolset.Msi
16 /// </summary> 16 /// </summary>
17 /// <param name="idtFile">The invalid idt file.</param> 17 /// <param name="idtFile">The invalid idt file.</param>
18 public WixInvalidIdtException(string idtFile) : 18 public WixInvalidIdtException(string idtFile) :
19 base(WixDataErrors.InvalidIdt(new SourceLineNumber(idtFile), idtFile)) 19 base(ErrorMessages.InvalidIdt(new SourceLineNumber(idtFile), idtFile))
20 { 20 {
21 } 21 }
22 22
@@ -26,7 +26,7 @@ namespace WixToolset.Msi
26 /// <param name="idtFile">The invalid idt file.</param> 26 /// <param name="idtFile">The invalid idt file.</param>
27 /// <param name="tableName">The table name of the invalid idt file.</param> 27 /// <param name="tableName">The table name of the invalid idt file.</param>
28 public WixInvalidIdtException(string idtFile, string tableName) : 28 public WixInvalidIdtException(string idtFile, string tableName) :
29 base(WixDataErrors.InvalidIdt(new SourceLineNumber(idtFile), idtFile, tableName)) 29 base(ErrorMessages.InvalidIdt(new SourceLineNumber(idtFile), idtFile, tableName))
30 { 30 {
31 } 31 }
32 } 32 }
diff --git a/src/WixToolset.Core.WindowsInstaller/Patch.cs b/src/WixToolset.Core.WindowsInstaller/Patch.cs
index 24a54859..c1914aca 100644
--- a/src/WixToolset.Core.WindowsInstaller/Patch.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Patch.cs
@@ -1232,14 +1232,5 @@ namespace WixToolset.Data
1232#endif 1232#endif
1233 throw new NotImplementedException(); 1233 throw new NotImplementedException();
1234 } 1234 }
1235
1236 /// <summary>
1237 /// Sends a message to the message delegate if there is one.
1238 /// </summary>
1239 /// <param name="mea">Message event arguments.</param>
1240 public void OnMessage(MessageEventArgs mea)
1241 {
1242 Messaging.Instance.OnMessage(mea);
1243 }
1244 } 1235 }
1245} 1236}
diff --git a/src/WixToolset.Core.WindowsInstaller/PatchTransform.cs b/src/WixToolset.Core.WindowsInstaller/PatchTransform.cs
index 9ba14843..0dc1e874 100644
--- a/src/WixToolset.Core.WindowsInstaller/PatchTransform.cs
+++ b/src/WixToolset.Core.WindowsInstaller/PatchTransform.cs
@@ -10,7 +10,7 @@ namespace WixToolset
10 using WixToolset.Data; 10 using WixToolset.Data;
11 using WixToolset.Extensibility; 11 using WixToolset.Extensibility;
12 12
13 public class PatchTransform : IMessageHandler 13 public class PatchTransform
14 { 14 {
15 private string baseline; 15 private string baseline;
16 private Intermediate transform; 16 private Intermediate transform;
@@ -264,14 +264,5 @@ namespace WixToolset
264#endif 264#endif
265 throw new NotImplementedException(); 265 throw new NotImplementedException();
266 } 266 }
267
268 /// <summary>
269 /// Sends a message to the message delegate if there is one.
270 /// </summary>
271 /// <param name="mea">Message event arguments.</param>
272 public void OnMessage(MessageEventArgs e)
273 {
274 Messaging.Instance.OnMessage(e);
275 }
276 } 267 }
277} 268}
diff --git a/src/WixToolset.Core.WindowsInstaller/Unbind/ExtractCabinetsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Unbind/ExtractCabinetsCommand.cs
index 1757e06f..ed3161ef 100644
--- a/src/WixToolset.Core.WindowsInstaller/Unbind/ExtractCabinetsCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Unbind/ExtractCabinetsCommand.cs
@@ -136,7 +136,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
136 } 136 }
137 catch (FileNotFoundException) 137 catch (FileNotFoundException)
138 { 138 {
139 throw new WixException(WixErrors.FileNotFound(new SourceLineNumber(this.InputFilePath), cabinetFile)); 139 throw new WixException(ErrorMessages.FileNotFound(new SourceLineNumber(this.InputFilePath), cabinetFile));
140 } 140 }
141 } 141 }
142 } 142 }
diff --git a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs
index 72e0c3c8..5d24d08a 100644
--- a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs
@@ -12,11 +12,12 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
12 using WixToolset.Data; 12 using WixToolset.Data;
13 using WixToolset.Data.WindowsInstaller; 13 using WixToolset.Data.WindowsInstaller;
14 using WixToolset.Data.WindowsInstaller.Rows; 14 using WixToolset.Data.WindowsInstaller.Rows;
15 using WixToolset.Extensibility.Services;
15 using WixToolset.Msi; 16 using WixToolset.Msi;
16 17
17 internal class UnbindDatabaseCommand 18 internal class UnbindDatabaseCommand
18 { 19 {
19 public UnbindDatabaseCommand(Messaging messaging, Database database, string databasePath, OutputType outputType, string exportBasePath, string intermediateFolder, bool isAdminImage, bool suppressDemodularization, bool skipSummaryInfo) 20 public UnbindDatabaseCommand(IMessaging messaging, Database database, string databasePath, OutputType outputType, string exportBasePath, string intermediateFolder, bool isAdminImage, bool suppressDemodularization, bool skipSummaryInfo)
20 { 21 {
21 this.Messaging = messaging; 22 this.Messaging = messaging;
22 this.Database = database; 23 this.Database = database;
@@ -31,7 +32,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
31 this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions(); 32 this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions();
32 } 33 }
33 34
34 public Messaging Messaging { get; } 35 public IMessaging Messaging { get; }
35 36
36 public Database Database { get; } 37 public Database Database { get; }
37 38
@@ -316,7 +317,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
316 317
317 if (!success) 318 if (!success)
318 { 319 {
319 this.Messaging.OnMessage(WixWarnings.BadColumnDataIgnored(row.SourceLineNumbers, Convert.ToString(intValue, CultureInfo.InvariantCulture), tableName, row.Fields[i].Column.Name)); 320 this.Messaging.Write(WarningMessages.BadColumnDataIgnored(row.SourceLineNumbers, Convert.ToString(intValue, CultureInfo.InvariantCulture), tableName, row.Fields[i].Column.Name));
320 } 321 }
321 break; 322 break;
322 case ColumnType.Object: 323 case ColumnType.Object:
@@ -480,7 +481,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
480 481
481 if (!File.Exists(wixFileRow.Source)) 482 if (!File.Exists(wixFileRow.Source))
482 { 483 {
483 throw new WixException(WixErrors.WixFileNotFound(wixFileRow.Source)); 484 throw new WixException(ErrorMessages.WixFileNotFound(wixFileRow.Source));
484 } 485 }
485 486
486 wixFileTable.Rows.Add(wixFileRow); 487 wixFileTable.Rows.Add(wixFileRow);
diff --git a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs
index 70f751f5..2b018013 100644
--- a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs
@@ -13,11 +13,12 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
13 using WixToolset.Data; 13 using WixToolset.Data;
14 using WixToolset.Data.WindowsInstaller; 14 using WixToolset.Data.WindowsInstaller;
15 using WixToolset.Extensibility; 15 using WixToolset.Extensibility;
16 using WixToolset.Extensibility.Services;
16 using WixToolset.Msi; 17 using WixToolset.Msi;
17 18
18 internal class UnbindTransformCommand 19 internal class UnbindTransformCommand
19 { 20 {
20 public UnbindTransformCommand(Messaging messaging, string transformFile, string exportBasePath, string intermediateFolder) 21 public UnbindTransformCommand(IMessaging messaging, string transformFile, string exportBasePath, string intermediateFolder)
21 { 22 {
22 this.Messaging = messaging; 23 this.Messaging = messaging;
23 this.TransformFile = transformFile; 24 this.TransformFile = transformFile;
@@ -27,7 +28,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
27 this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions(); 28 this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions();
28 } 29 }
29 30
30 private Messaging Messaging { get; } 31 private IMessaging Messaging { get; }
31 32
32 private string TransformFile { get; } 33 private string TransformFile { get; }
33 34
@@ -152,7 +153,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind
152 // this commonly happens when the transform was built 153 // this commonly happens when the transform was built
153 // against a database schema different from the internal 154 // against a database schema different from the internal
154 // table definitions 155 // table definitions
155 throw new WixException(WixErrors.TransformSchemaMismatch()); 156 throw new WixException(ErrorMessages.TransformSchemaMismatch());
156 } 157 }
157 } 158 }
158 159
diff --git a/src/WixToolset.Core.WindowsInstaller/UnbindContext.cs b/src/WixToolset.Core.WindowsInstaller/UnbindContext.cs
index ed55f312..ff71bea4 100644
--- a/src/WixToolset.Core.WindowsInstaller/UnbindContext.cs
+++ b/src/WixToolset.Core.WindowsInstaller/UnbindContext.cs
@@ -2,12 +2,15 @@
2 2
3namespace WixToolset.Core 3namespace WixToolset.Core
4{ 4{
5 using WixToolset.Data; 5 using System;
6 using WixToolset.Extensibility; 6 using WixToolset.Extensibility;
7 using WixToolset.Extensibility.Services;
7 8
8 internal class UnbindContext : IUnbindContext 9 internal class UnbindContext : IUnbindContext
9 { 10 {
10 public Messaging Messaging { get; } = Messaging.Instance; 11 public IServiceProvider ServiceProvider { get; }
12
13 public IMessaging Messaging { get; set; }
11 14
12 public string ExportBasePath { get; set; } 15 public string ExportBasePath { get; set; }
13 16
diff --git a/src/WixToolset.Core.WindowsInstaller/Unbinder.cs b/src/WixToolset.Core.WindowsInstaller/Unbinder.cs
index d2d27d45..db121fc0 100644
--- a/src/WixToolset.Core.WindowsInstaller/Unbinder.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Unbinder.cs
@@ -53,11 +53,11 @@ namespace WixToolset.Core
53 { 53 {
54 if (OutputType.Transform == outputType) 54 if (OutputType.Transform == outputType)
55 { 55 {
56 throw new WixException(WixErrors.FileNotFound(null, file, "Transform")); 56 throw new WixException(ErrorMessages.FileNotFound(null, file, "Transform"));
57 } 57 }
58 else 58 else
59 { 59 {
60 throw new WixException(WixErrors.FileNotFound(null, file, "Database")); 60 throw new WixException(ErrorMessages.FileNotFound(null, file, "Database"));
61 } 61 }
62 } 62 }
63 63
diff --git a/src/WixToolset.Core.WindowsInstaller/Validator.cs b/src/WixToolset.Core.WindowsInstaller/Validator.cs
index eb17d8af..d553cc71 100644
--- a/src/WixToolset.Core.WindowsInstaller/Validator.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Validator.cs
@@ -22,7 +22,7 @@ namespace WixToolset.Core.WindowsInstaller
22 /// <summary> 22 /// <summary>
23 /// Runs internal consistency evaluators (ICEs) from cub files against a database. 23 /// Runs internal consistency evaluators (ICEs) from cub files against a database.
24 /// </summary> 24 /// </summary>
25 public sealed class Validator : IMessageHandler 25 public sealed class Validator
26 { 26 {
27 private string actionName; 27 private string actionName;
28 private StringCollection cubeFiles; 28 private StringCollection cubeFiles;
@@ -30,15 +30,17 @@ namespace WixToolset.Core.WindowsInstaller
30 private Output output; 30 private Output output;
31 private InstallUIHandler validationUIHandler; 31 private InstallUIHandler validationUIHandler;
32 private bool validationSessionComplete; 32 private bool validationSessionComplete;
33 private readonly IMessaging messaging;
33 34
34 /// <summary> 35 /// <summary>
35 /// Instantiate a new Validator. 36 /// Instantiate a new Validator.
36 /// </summary> 37 /// </summary>
37 public Validator() 38 public Validator(IMessaging messaging)
38 { 39 {
39 this.cubeFiles = new StringCollection(); 40 this.cubeFiles = new StringCollection();
40 this.extension = new ValidatorExtension(); 41 this.extension = new ValidatorExtension(messaging);
41 this.validationUIHandler = new InstallUIHandler(this.ValidationUIHandler); 42 this.validationUIHandler = new InstallUIHandler(this.ValidationUIHandler);
43 this.messaging = messaging;
42 } 44 }
43 45
44 /// <summary> 46 /// <summary>
@@ -127,7 +129,7 @@ namespace WixToolset.Core.WindowsInstaller
127 { 129 {
128 if (!mutex.WaitOne(0, false)) 130 if (!mutex.WaitOne(0, false))
129 { 131 {
130 this.OnMessage(WixVerboses.ValidationSerialized()); 132 this.messaging.Write(VerboseMessages.ValidationSerialized());
131 mutex.WaitOne(); 133 mutex.WaitOne();
132 } 134 }
133 135
@@ -176,7 +178,7 @@ namespace WixToolset.Core.WindowsInstaller
176 { 178 {
177 if (0x6E == e.NativeErrorCode) // ERROR_OPEN_FAILED 179 if (0x6E == e.NativeErrorCode) // ERROR_OPEN_FAILED
178 { 180 {
179 throw new WixException(WixErrors.CubeFileNotFound(cubeFile)); 181 throw new WixException(ErrorMessages.CubeFileNotFound(cubeFile));
180 } 182 }
181 183
182 throw; 184 throw;
@@ -248,7 +250,7 @@ namespace WixToolset.Core.WindowsInstaller
248 } 250 }
249 catch (Win32Exception e) 251 catch (Win32Exception e)
250 { 252 {
251 if (!Messaging.Instance.EncounteredError) 253 if (!this.messaging.EncounteredError)
252 { 254 {
253 throw e; 255 throw e;
254 } 256 }
@@ -270,7 +272,7 @@ namespace WixToolset.Core.WindowsInstaller
270 catch (Win32Exception e) 272 catch (Win32Exception e)
271 { 273 {
272 // avoid displaying errors twice since one may have already occurred in the UI handler 274 // avoid displaying errors twice since one may have already occurred in the UI handler
273 if (!Messaging.Instance.EncounteredError) 275 if (!this.messaging.EncounteredError)
274 { 276 {
275 if (0x6E == e.NativeErrorCode) // ERROR_OPEN_FAILED 277 if (0x6E == e.NativeErrorCode) // ERROR_OPEN_FAILED
276 { 278 {
@@ -278,23 +280,23 @@ namespace WixToolset.Core.WindowsInstaller
278 // this would be the temporary copy and there would be 280 // this would be the temporary copy and there would be
279 // no final output since the error occured; during smoke 281 // no final output since the error occured; during smoke
280 // they should know the path passed into smoke 282 // they should know the path passed into smoke
281 this.OnMessage(WixErrors.ValidationFailedToOpenDatabase()); 283 this.messaging.Write(ErrorMessages.ValidationFailedToOpenDatabase());
282 } 284 }
283 else if (0x64D == e.NativeErrorCode) 285 else if (0x64D == e.NativeErrorCode)
284 { 286 {
285 this.OnMessage(WixErrors.ValidationFailedDueToLowMsiEngine()); 287 this.messaging.Write(ErrorMessages.ValidationFailedDueToLowMsiEngine());
286 } 288 }
287 else if (0x654 == e.NativeErrorCode) 289 else if (0x654 == e.NativeErrorCode)
288 { 290 {
289 this.OnMessage(WixErrors.ValidationFailedDueToInvalidPackage()); 291 this.messaging.Write(ErrorMessages.ValidationFailedDueToInvalidPackage());
290 } 292 }
291 else if (0x658 == e.NativeErrorCode) 293 else if (0x658 == e.NativeErrorCode)
292 { 294 {
293 this.OnMessage(WixErrors.ValidationFailedDueToMultilanguageMergeModule()); 295 this.messaging.Write(ErrorMessages.ValidationFailedDueToMultilanguageMergeModule());
294 } 296 }
295 else if (0x659 == e.NativeErrorCode) 297 else if (0x659 == e.NativeErrorCode)
296 { 298 {
297 this.OnMessage(WixWarnings.ValidationFailedDueToSystemPolicy()); 299 this.messaging.Write(WarningMessages.ValidationFailedDueToSystemPolicy());
298 } 300 }
299 else 301 else
300 { 302 {
@@ -305,7 +307,7 @@ namespace WixToolset.Core.WindowsInstaller
305 msgTemp = String.Concat("Action - '", this.actionName, "' ", e.Message); 307 msgTemp = String.Concat("Action - '", this.actionName, "' ", e.Message);
306 } 308 }
307 309
308 this.OnMessage(WixErrors.Win32Exception(e.NativeErrorCode, msgTemp)); 310 this.messaging.Write(ErrorMessages.Win32Exception(e.NativeErrorCode, msgTemp));
309 } 311 }
310 } 312 }
311 } 313 }
@@ -322,16 +324,6 @@ namespace WixToolset.Core.WindowsInstaller
322 } 324 }
323 } 325 }
324 326
325 /// <summary>
326 /// Sends a message to the message delegate if there is one.
327 /// </summary>
328 /// <param name="mea">Message event arguments.</param>
329 public void OnMessage(MessageEventArgs e)
330 {
331 Messaging.Instance.OnMessage(e);
332 this.extension.OnMessage(e);
333 }
334
335 public static Validator CreateFromContext(IBindContext context, string cubeFilename) 327 public static Validator CreateFromContext(IBindContext context, string cubeFilename)
336 { 328 {
337 Validator validator = null; 329 Validator validator = null;
@@ -339,7 +331,7 @@ namespace WixToolset.Core.WindowsInstaller
339 // Tell the binder about the validator if validation isn't suppressed 331 // Tell the binder about the validator if validation isn't suppressed
340 if (!context.SuppressValidation) 332 if (!context.SuppressValidation)
341 { 333 {
342 validator = new Validator(); 334 validator = new Validator(context.Messaging);
343 validator.IntermediateFolder = Path.Combine(context.IntermediateFolder, "validate"); 335 validator.IntermediateFolder = Path.Combine(context.IntermediateFolder, "validate");
344 336
345 // set the default cube file 337 // set the default cube file
@@ -378,7 +370,7 @@ namespace WixToolset.Core.WindowsInstaller
378 } 370 }
379 catch (WixException ex) 371 catch (WixException ex)
380 { 372 {
381 this.OnMessage(ex.Error); 373 this.messaging.Write(ex.Error);
382 } 374 }
383 375
384 return 1; 376 return 1;
diff --git a/src/WixToolset.Core.WindowsInstaller/ValidatorExtension.cs b/src/WixToolset.Core.WindowsInstaller/ValidatorExtension.cs
index 67f5962c..48f73bf2 100644
--- a/src/WixToolset.Core.WindowsInstaller/ValidatorExtension.cs
+++ b/src/WixToolset.Core.WindowsInstaller/ValidatorExtension.cs
@@ -6,23 +6,26 @@ namespace WixToolset.Extensibility
6 using System.Collections; 6 using System.Collections;
7 using WixToolset.Data; 7 using WixToolset.Data;
8 using WixToolset.Data.WindowsInstaller; 8 using WixToolset.Data.WindowsInstaller;
9 using WixToolset.Extensibility.Services;
9 10
10 /// <summary> 11 /// <summary>
11 /// Base class for creating a validator extension. This default implementation 12 /// Base class for creating a validator extension. This default implementation
12 /// will fire and event with the ICE name and description. 13 /// will fire and event with the ICE name and description.
13 /// </summary> 14 /// </summary>
14 public class ValidatorExtension : IMessageHandler 15 public class ValidatorExtension
15 { 16 {
16 private string databaseFile; 17 private string databaseFile;
17 private Hashtable indexedSourceLineNumbers; 18 private Hashtable indexedSourceLineNumbers;
18 private Output output; 19 private Output output;
19 private SourceLineNumber sourceLineNumbers; 20 private SourceLineNumber sourceLineNumbers;
21 private readonly IMessaging messaging;
20 22
21 /// <summary> 23 /// <summary>
22 /// Instantiate a new <see cref="ValidatorExtension"/>. 24 /// Instantiate a new <see cref="ValidatorExtension"/>.
23 /// </summary> 25 /// </summary>
24 public ValidatorExtension() 26 public ValidatorExtension(IMessaging messaging)
25 { 27 {
28 this.messaging = messaging;
26 } 29 }
27 30
28 /// <summary> 31 /// <summary>
@@ -183,11 +186,11 @@ namespace WixToolset.Extensibility
183 { 186 {
184 if (null == action) 187 if (null == action)
185 { 188 {
186 throw new WixException(WixErrors.UnexpectedExternalUIMessage(message)); 189 throw new WixException(ErrorMessages.UnexpectedExternalUIMessage(message));
187 } 190 }
188 else 191 else
189 { 192 {
190 throw new WixException(WixErrors.UnexpectedExternalUIMessage(message, action)); 193 throw new WixException(ErrorMessages.UnexpectedExternalUIMessage(message, action));
191 } 194 }
192 } 195 }
193 196
@@ -209,16 +212,16 @@ namespace WixToolset.Extensibility
209 { 212 {
210 case "0": 213 case "0":
211 case "1": 214 case "1":
212 this.OnMessage(WixErrors.ValidationError(messageSourceLineNumbers, messageParts[0], messageParts[2])); 215 this.messaging.Write(ErrorMessages.ValidationError(messageSourceLineNumbers, messageParts[0], messageParts[2]));
213 break; 216 break;
214 case "2": 217 case "2":
215 this.OnMessage(WixWarnings.ValidationWarning(messageSourceLineNumbers, messageParts[0], messageParts[2])); 218 this.messaging.Write(WarningMessages.ValidationWarning(messageSourceLineNumbers, messageParts[0], messageParts[2]));
216 break; 219 break;
217 case "3": 220 case "3":
218 this.OnMessage(WixVerboses.ValidationInfo(messageParts[0], messageParts[2])); 221 this.messaging.Write(VerboseMessages.ValidationInfo(messageParts[0], messageParts[2]));
219 break; 222 break;
220 default: 223 default:
221 throw new WixException(WixErrors.InvalidValidatorMessageType(messageParts[1])); 224 throw new WixException(ErrorMessages.InvalidValidatorMessageType(messageParts[1]));
222 } 225 }
223 } 226 }
224 227
@@ -264,7 +267,7 @@ namespace WixToolset.Extensibility
264 267
265 if (this.indexedSourceLineNumbers.ContainsKey(key)) 268 if (this.indexedSourceLineNumbers.ContainsKey(key))
266 { 269 {
267 this.OnMessage(WixWarnings.DuplicatePrimaryKey(row.SourceLineNumbers, primaryKey, table.Name)); 270 this.messaging.Write(WarningMessages.DuplicatePrimaryKey(row.SourceLineNumbers, primaryKey, table.Name));
268 } 271 }
269 else 272 else
270 { 273 {
@@ -281,20 +284,5 @@ namespace WixToolset.Extensibility
281 // use the file name as the source line information 284 // use the file name as the source line information
282 return this.sourceLineNumbers; 285 return this.sourceLineNumbers;
283 } 286 }
284
285 /// <summary>
286 /// Sends a message to the <see cref="Message"/> delegate if there is one.
287 /// </summary>
288 /// <param name="e">Message event arguments.</param>
289 /// <remarks>
290 /// <para><b>Notes to Inheritors:</b> When overriding <b>OnMessage</b>
291 /// in a derived class, be sure to call the base class's
292 /// <b>OnMessage</b> method so that registered delegates recieve
293 /// the event.</para>
294 /// </remarks>
295 public virtual void OnMessage(MessageEventArgs e)
296 {
297 Messaging.Instance.OnMessage(e);
298 }
299 } 287 }
300} 288}
diff --git a/src/WixToolset.Core.WindowsInstaller/WindowsInstallerStandardInternal.cs b/src/WixToolset.Core.WindowsInstaller/WindowsInstallerStandardInternal.cs
index 3b4721a6..759bda14 100644
--- a/src/WixToolset.Core.WindowsInstaller/WindowsInstallerStandardInternal.cs
+++ b/src/WixToolset.Core.WindowsInstaller/WindowsInstallerStandardInternal.cs
@@ -16,7 +16,9 @@ namespace WixToolset.Core.WindowsInstaller
16 private static readonly object lockObject = new object(); 16 private static readonly object lockObject = new object();
17 17
18 private static TableDefinitionCollection tableDefinitions; 18 private static TableDefinitionCollection tableDefinitions;
19#if REVISIT_FOR_PATCHING
19 private static WixActionRowCollection standardActions; 20 private static WixActionRowCollection standardActions;
21#endif
20 22
21 /// <summary> 23 /// <summary>
22 /// Gets the table definitions stored in this assembly. 24 /// Gets the table definitions stored in this assembly.
@@ -57,7 +59,7 @@ namespace WixToolset.Core.WindowsInstaller
57 } 59 }
58 60
59 return WindowsInstallerStandardInternal.standardActions; 61 return WindowsInstallerStandardInternal.standardActions;
60#endif 62#endif
61 throw new NotImplementedException(); 63 throw new NotImplementedException();
62 } 64 }
63 } 65 }