aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs')
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs739
1 files changed, 224 insertions, 515 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
index 5a61b63c..30a19a4b 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
@@ -3,21 +3,15 @@
3namespace WixToolset.Core.WindowsInstaller.Bind 3namespace WixToolset.Core.WindowsInstaller.Bind
4{ 4{
5 using System; 5 using System;
6 using System.Collections;
7 using System.Collections.Generic; 6 using System.Collections.Generic;
8 using System.Diagnostics;
9 using System.Globalization;
10 using System.IO; 7 using System.IO;
11 using System.Linq; 8 using System.Linq;
12 using WixToolset.Bind;
13 using WixToolset.Core.Bind; 9 using WixToolset.Core.Bind;
14 using WixToolset.Core.WindowsInstaller.Databases;
15 using WixToolset.Data; 10 using WixToolset.Data;
16 using WixToolset.Data.Bind; 11 using WixToolset.Data.Bind;
17 using WixToolset.Data.Rows; 12 using WixToolset.Data.Tuples;
18 using WixToolset.Extensibility; 13 using WixToolset.Extensibility;
19 using WixToolset.Extensibility.Services; 14 using WixToolset.Extensibility.Services;
20 using WixToolset.Msi;
21 15
22 /// <summary> 16 /// <summary>
23 /// Binds a databse. 17 /// Binds a databse.
@@ -25,11 +19,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind
25 internal class BindDatabaseCommand 19 internal class BindDatabaseCommand
26 { 20 {
27 // As outlined in RFC 4122, this is our namespace for generating name-based (version 3) UUIDs. 21 // As outlined in RFC 4122, this is our namespace for generating name-based (version 3) UUIDs.
28 private static readonly Guid WixComponentGuidNamespace = new Guid("{3064E5C6-FB63-4FE9-AC49-E446A792EFA5}"); 22 internal static readonly Guid WixComponentGuidNamespace = new Guid("{3064E5C6-FB63-4FE9-AC49-E446A792EFA5}");
29 23
30 public BindDatabaseCommand(IBindContext context, Validator validator) 24 public BindDatabaseCommand(IBindContext context, Validator validator)
31 { 25 {
32 this.TableDefinitions = WindowsInstallerStandard.GetTableDefinitions(); 26 this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions();
33 27
34 this.BindPaths = context.BindPaths; 28 this.BindPaths = context.BindPaths;
35 this.CabbingThreadCount = context.CabbingThreadCount; 29 this.CabbingThreadCount = context.CabbingThreadCount;
@@ -73,8 +67,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
73 67
74 private Intermediate Intermediate { get; } 68 private Intermediate Intermediate { get; }
75 69
76 private Output Output { get; }
77
78 private string OutputPath { get; } 70 private string OutputPath { get; }
79 71
80 private bool SuppressAddingValidationRows { get; } 72 private bool SuppressAddingValidationRows { get; }
@@ -95,22 +87,16 @@ namespace WixToolset.Core.WindowsInstaller.Bind
95 87
96 public void Execute() 88 public void Execute()
97 { 89 {
98 this.Intermediate.Save(this.OutputPath); 90 var section = this.Intermediate.Sections.Single();
99#if FINISH
100 List<FileTransfer> fileTransfers = new List<FileTransfer>();
101 91
102 HashSet<string> suppressedTableNames = new HashSet<string>(); 92 var fileTransfers = new List<FileTransfer>();
103 93
104 // If there are any fields to resolve later, create the cache to populate during bind. 94 var suppressedTableNames = new HashSet<string>();
105 IDictionary<string, string> variableCache = null;
106 if (this.DelayedFields.Any())
107 {
108 variableCache = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
109 }
110 95
111 this.LocalizeUI(this.Output.Tables); 96 // If there are any fields to resolve later, create the cache to populate during bind.
97 var variableCache = this.DelayedFields.Any() ? new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) : null;
112 98
113 this.Output = CreateOutputFromIR(this.Intermediate); 99 this.LocalizeUI(section);
114 100
115 // Process the summary information table before the other tables. 101 // Process the summary information table before the other tables.
116 bool compressed; 102 bool compressed;
@@ -118,8 +104,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
118 int installerVersion; 104 int installerVersion;
119 string modularizationGuid; 105 string modularizationGuid;
120 { 106 {
121 BindSummaryInfoCommand command = new BindSummaryInfoCommand(); 107 var command = new BindSummaryInfoCommand(section);
122 command.Output = this.Output;
123 command.Execute(); 108 command.Execute();
124 109
125 compressed = command.Compressed; 110 compressed = command.Compressed;
@@ -128,42 +113,61 @@ namespace WixToolset.Core.WindowsInstaller.Bind
128 modularizationGuid = command.ModularizationGuid; 113 modularizationGuid = command.ModularizationGuid;
129 } 114 }
130 115
131 // Stop processing if an error previously occurred. 116 // Add binder variables for all properties.
132 if (Messaging.Instance.EncounteredError) 117 if (SectionType.Product == section.Type || variableCache != null)
133 {
134 return;
135 }
136
137 // Modularize identifiers and add tables with real streams to the import tables.
138 if (OutputType.Module == this.Output.Type)
139 { 118 {
140 // Gather all the suppress modularization identifiers 119 foreach (var propertyRow in section.Tuples.OfType<PropertyTuple>())
141 HashSet<string> suppressModularizationIdentifiers = null;
142 Table wixSuppressModularizationTable = this.Output.Tables["WixSuppressModularization"];
143 if (null != wixSuppressModularizationTable)
144 { 120 {
145 suppressModularizationIdentifiers = new HashSet<string>(wixSuppressModularizationTable.Rows.Select(row => (string)row[0])); 121 // Set the ProductCode if it is to be generated.
146 } 122 if ("ProductCode".Equals(propertyRow.Property, StringComparison.Ordinal) && "*".Equals(propertyRow.Value, StringComparison.Ordinal))
123 {
124 propertyRow.Value = Common.GenerateGuid();
147 125
148 foreach (Table table in this.Output.Tables) 126#if TODO_FIX_INSTANCE_TRANSFORM
149 { 127 // Update the target ProductCode in any instance transforms.
150 table.Modularize(modularizationGuid, suppressModularizationIdentifiers); 128 foreach (SubStorage subStorage in this.Output.SubStorages)
129 {
130 Output subStorageOutput = subStorage.Data;
131 if (OutputType.Transform != subStorageOutput.Type)
132 {
133 continue;
134 }
135
136 Table instanceSummaryInformationTable = subStorageOutput.Tables["_SummaryInformation"];
137 foreach (Row row in instanceSummaryInformationTable.Rows)
138 {
139 if ((int)SummaryInformation.Transform.ProductCodes == row.FieldAsInteger(0))
140 {
141 row[1] = row.FieldAsString(1).Replace("*", propertyRow.Value);
142 break;
143 }
144 }
145 }
146#endif
147 }
148
149 // Add the property name and value to the variableCache.
150 if (variableCache != null)
151 {
152 var key = String.Concat("property.", propertyRow.Property);
153 variableCache[key] = propertyRow.Value;
154 }
151 } 155 }
152 } 156 }
153 157
154 // This must occur after all variables and source paths have been resolved and after modularization. 158 // Sequence all the actions.
155 List<FileFacade> fileFacades;
156 { 159 {
157 GetFileFacadesCommand command = new GetFileFacadesCommand(); 160 var command = new SequenceActionsCommand(section);
158 command.FileTable = this.Output.Tables["File"]; 161 command.Messaging = Messaging.Instance;
159 command.WixFileTable = this.Output.Tables["WixFile"];
160 command.WixDeltaPatchFileTable = this.Output.Tables["WixDeltaPatchFile"];
161 command.WixDeltaPatchSymbolPathsTable = this.Output.Tables["WixDeltaPatchSymbolPaths"];
162 command.Execute(); 162 command.Execute();
163 }
163 164
164 fileFacades = command.FileFacades; 165 {
166 var command = new CreateSpecialPropertiesCommand(section);
167 command.Execute();
165 } 168 }
166 169
170#if TODO_FINISH_PATCH
167 ////if (OutputType.Patch == this.Output.Type) 171 ////if (OutputType.Patch == this.Output.Type)
168 ////{ 172 ////{
169 //// foreach (SubStorage substorage in this.Output.SubStorages) 173 //// foreach (SubStorage substorage in this.Output.SubStorages)
@@ -183,87 +187,72 @@ namespace WixToolset.Core.WindowsInstaller.Bind
183 //// this.MergeUnrealTables(transform.Tables); 187 //// this.MergeUnrealTables(transform.Tables);
184 //// } 188 //// }
185 ////} 189 ////}
186 190#endif
187 {
188 CreateSpecialPropertiesCommand command = new CreateSpecialPropertiesCommand();
189 command.PropertyTable = this.Output.Tables["Property"];
190 command.WixPropertyTable = this.Output.Tables["WixProperty"];
191 command.Execute();
192 }
193 191
194 if (Messaging.Instance.EncounteredError) 192 if (Messaging.Instance.EncounteredError)
195 { 193 {
196 return; 194 return;
197 } 195 }
198 196
199 // Add binder variables for all properties. 197 Messaging.Instance.OnMessage(WixVerboses.UpdatingFileInformation());
200 Table propertyTable = this.Output.Tables["Property"]; 198
201 if (null != propertyTable) 199 // This must occur after all variables and source paths have been resolved.
200 List<FileFacade> fileFacades;
202 { 201 {
203 foreach (PropertyRow propertyRow in propertyTable.Rows) 202 var command = new GetFileFacadesCommand(section);
204 { 203 command.Execute();
205 // Set the ProductCode if it is to be generated.
206 if (OutputType.Product == this.Output.Type && "ProductCode".Equals(propertyRow.Property, StringComparison.Ordinal) && "*".Equals(propertyRow.Value, StringComparison.Ordinal))
207 {
208 propertyRow.Value = Common.GenerateGuid();
209 204
210 // Update the target ProductCode in any instance transforms. 205 fileFacades = command.FileFacades;
211 foreach (SubStorage subStorage in this.Output.SubStorages) 206 }
212 {
213 Output subStorageOutput = subStorage.Data;
214 if (OutputType.Transform != subStorageOutput.Type)
215 {
216 continue;
217 }
218 207
219 Table instanceSummaryInformationTable = subStorageOutput.Tables["_SummaryInformation"]; 208 // Extract files that come from binary .wixlibs and WixExtensions (this does not extract files from merge modules).
220 foreach (Row row in instanceSummaryInformationTable.Rows) 209 {
221 { 210 var command = new ExtractEmbeddedFilesCommand(this.ExpectedEmbeddedFiles);
222 if ((int)SummaryInformation.Transform.ProductCodes == row.FieldAsInteger(0)) 211 command.Execute();
223 { 212 }
224 row[1] = row.FieldAsString(1).Replace("*", propertyRow.Value);
225 break;
226 }
227 }
228 }
229 }
230 213
231 // Add the property name and value to the variableCache. 214 // Gather information about files that did not come from merge modules (i.e. rows with a reference to the File table).
232 if (null != variableCache) 215 {
233 { 216 var command = new UpdateFileFacadesCommand(section);
234 string key = String.Concat("property.", Common.Demodularize(this.Output.Type, modularizationGuid, propertyRow.Property)); 217 command.FileFacades = fileFacades;
235 variableCache[key] = propertyRow.Value; 218 command.UpdateFileFacades = fileFacades.Where(f => !f.FromModule);
236 } 219 command.OverwriteHash = true;
237 } 220 command.TableDefinitions = this.TableDefinitions;
221 command.VariableCache = variableCache;
222 command.Execute();
238 } 223 }
239 224
240 // Extract files that come from cabinet files (this does not extract files from merge modules). 225 // Now that the variable cache is populated, resolve any delayed fields.
226 if (this.DelayedFields.Any())
241 { 227 {
242 ExtractEmbeddedFilesCommand command = new ExtractEmbeddedFilesCommand(); 228 var command = new ResolveDelayedFieldsCommand(this.DelayedFields, variableCache);
243 command.FilesWithEmbeddedFiles = this.ExpectedEmbeddedFiles;
244 command.Execute(); 229 command.Execute();
245 } 230 }
246 231
247 if (OutputType.Product == this.Output.Type) 232 // Set generated component guids.
233 {
234 var command = new CalculateComponentGuids(section);
235 command.Execute();
236 }
237
238 if (SectionType.Product == section.Type)
248 { 239 {
249 // Retrieve files and their information from merge modules. 240 // Retrieve files and their information from merge modules.
250 Table wixMergeTable = this.Output.Tables["WixMerge"]; 241 var wixMergeTuples = section.Tuples.OfType<WixMergeTuple>().ToList();
251 242
252 if (null != wixMergeTable) 243 if (wixMergeTuples.Any())
253 { 244 {
254 ExtractMergeModuleFilesCommand command = new ExtractMergeModuleFilesCommand(); 245 var command = new ExtractMergeModuleFilesCommand(section, wixMergeTuples);
255 command.FileFacades = fileFacades; 246 command.FileFacades = fileFacades;
256 command.FileTable = this.Output.Tables["File"];
257 command.WixFileTable = this.Output.Tables["WixFile"];
258 command.WixMergeTable = wixMergeTable;
259 command.OutputInstallerVersion = installerVersion; 247 command.OutputInstallerVersion = installerVersion;
260 command.SuppressLayout = this.SuppressLayout; 248 command.SuppressLayout = this.SuppressLayout;
261 command.TempFilesLocation = this.IntermediateFolder; 249 command.IntermediateFolder = this.IntermediateFolder;
262 command.Execute(); 250 command.Execute();
263 251
264 fileFacades.AddRange(command.MergeModulesFileFacades); 252 fileFacades.AddRange(command.MergeModulesFileFacades);
265 } 253 }
266 } 254 }
255#if TODO_FINISH_PATCH
267 else if (OutputType.Patch == this.Output.Type) 256 else if (OutputType.Patch == this.Output.Type)
268 { 257 {
269 // Merge transform data into the output object. 258 // Merge transform data into the output object.
@@ -271,6 +260,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
271 260
272 fileFacades.AddRange(filesFromTransform); 261 fileFacades.AddRange(filesFromTransform);
273 } 262 }
263#endif
274 264
275 // stop processing if an error previously occurred 265 // stop processing if an error previously occurred
276 if (Messaging.Instance.EncounteredError) 266 if (Messaging.Instance.EncounteredError)
@@ -278,51 +268,19 @@ namespace WixToolset.Core.WindowsInstaller.Bind
278 return; 268 return;
279 } 269 }
280 270
281 Messaging.Instance.OnMessage(WixVerboses.UpdatingFileInformation()); 271#if TODO_FIX_INSTANCE_TRANSFORM
282
283 // Gather information about files that did not come from merge modules (i.e. rows with a reference to the File table).
284 {
285 UpdateFileFacadesCommand command = new UpdateFileFacadesCommand();
286 command.FileFacades = fileFacades;
287 command.UpdateFileFacades = fileFacades.Where(f => !f.FromModule);
288 command.ModularizationGuid = modularizationGuid;
289 command.Output = this.Output;
290 command.OverwriteHash = true;
291 command.TableDefinitions = this.TableDefinitions;
292 command.VariableCache = variableCache;
293 command.Execute();
294 }
295
296 // Set generated component guids.
297 this.SetComponentGuids(this.Output);
298
299 // With the Component Guids set now we can create instance transforms. 272 // With the Component Guids set now we can create instance transforms.
300 this.CreateInstanceTransforms(this.Output); 273 this.CreateInstanceTransforms(this.Output);
301 274#endif
302 this.ValidateComponentGuids(this.Output);
303
304 this.UpdateControlText(this.Output);
305
306 if (this.DelayedFields.Any())
307 {
308 ResolveDelayedFieldsCommand command = new ResolveDelayedFieldsCommand();
309 command.OutputType = this.Output.Type;
310 command.DelayedFields = this.DelayedFields;
311 command.ModularizationGuid = null;
312 command.VariableCache = variableCache;
313 command.Execute();
314 }
315 275
316 // Assign files to media. 276 // Assign files to media.
317 RowDictionary<MediaRow> assignedMediaRows; 277 Dictionary<int, MediaTuple> assignedMediaRows;
318 Dictionary<MediaRow, IEnumerable<FileFacade>> filesByCabinetMedia; 278 Dictionary<MediaTuple, IEnumerable<FileFacade>> filesByCabinetMedia;
319 IEnumerable<FileFacade> uncompressedFiles; 279 IEnumerable<FileFacade> uncompressedFiles;
320 { 280 {
321 AssignMediaCommand command = new AssignMediaCommand(); 281 var command = new AssignMediaCommand(section);
322 command.FilesCompressed = compressed;
323 command.FileFacades = fileFacades; 282 command.FileFacades = fileFacades;
324 command.Output = this.Output; 283 command.FilesCompressed = compressed;
325 command.TableDefinitions = this.TableDefinitions;
326 command.Execute(); 284 command.Execute();
327 285
328 assignedMediaRows = command.MediaRows; 286 assignedMediaRows = command.MediaRows;
@@ -330,15 +288,40 @@ namespace WixToolset.Core.WindowsInstaller.Bind
330 uncompressedFiles = command.UncompressedFileFacades; 288 uncompressedFiles = command.UncompressedFileFacades;
331 } 289 }
332 290
333 // Update file sequence.
334 this.UpdateMediaSequences(this.Output.Type, fileFacades, assignedMediaRows);
335
336 // stop processing if an error previously occurred 291 // stop processing if an error previously occurred
337 if (Messaging.Instance.EncounteredError) 292 if (Messaging.Instance.EncounteredError)
338 { 293 {
339 return; 294 return;
340 } 295 }
341 296
297 // Try to put as much above here as possible, updating the IR is better.
298 Output output;
299 {
300 var command = new CreateOutputFromIRCommand(section, this.TableDefinitions);
301 command.Execute();
302
303 output = command.Output;
304 }
305
306 // Update file sequence.
307 {
308 var command = new UpdateMediaSequencesCommand(output, fileFacades, assignedMediaRows);
309 command.Execute();
310 }
311
312 // Modularize identifiers and add tables with real streams to the import tables.
313 if (OutputType.Module == output.Type)
314 {
315 // Gather all the suppress modularization identifiers
316 var suppressModularizationIdentifiers = new HashSet<string>(section.Tuples.OfType<WixSuppressModularizationTuple>().Select(s => s.WixSuppressModularization));
317
318 foreach (var table in output.Tables)
319 {
320 table.Modularize(modularizationGuid, suppressModularizationIdentifiers);
321 }
322 }
323
324#if TODO_FINISH_UPDATE
342 // Extended binder extensions can be called now that fields are resolved. 325 // Extended binder extensions can be called now that fields are resolved.
343 { 326 {
344 Table updatedFiles = this.Output.EnsureTable(this.TableDefinitions["WixBindUpdatedFiles"]); 327 Table updatedFiles = this.Output.EnsureTable(this.TableDefinitions["WixBindUpdatedFiles"]);
@@ -372,27 +355,27 @@ namespace WixToolset.Core.WindowsInstaller.Bind
372 command.Execute(); 355 command.Execute();
373 } 356 }
374 } 357 }
358#endif
375 359
376 // stop processing if an error previously occurred 360 // Stop processing if an error previously occurred.
377 if (Messaging.Instance.EncounteredError) 361 if (Messaging.Instance.EncounteredError)
378 { 362 {
379 return; 363 return;
380 } 364 }
381 365
366 // Ensure the intermediate folder is created since delta patches will be
367 // created there.
382 Directory.CreateDirectory(this.IntermediateFolder); 368 Directory.CreateDirectory(this.IntermediateFolder);
383 369
384 if (OutputType.Patch == this.Output.Type && this.DeltaBinaryPatch) 370 if (SectionType.Patch == section.Type && this.DeltaBinaryPatch)
385 { 371 {
386 CreateDeltaPatchesCommand command = new CreateDeltaPatchesCommand(); 372 var command = new CreateDeltaPatchesCommand(fileFacades, this.IntermediateFolder, section.Tuples.OfType<WixPatchIdTuple>().FirstOrDefault());
387 command.FileFacades = fileFacades;
388 command.WixPatchIdTable = this.Output.Tables["WixPatchId"];
389 command.TempFilesLocation = this.IntermediateFolder;
390 command.Execute(); 373 command.Execute();
391 } 374 }
392 375
393 // create cabinet files and process uncompressed files 376 // create cabinet files and process uncompressed files
394 string layoutDirectory = Path.GetDirectoryName(this.OutputPath); 377 string layoutDirectory = Path.GetDirectoryName(this.OutputPath);
395 if (!this.SuppressLayout || OutputType.Module == this.Output.Type) 378 if (!this.SuppressLayout || OutputType.Module == output.Type)
396 { 379 {
397 Messaging.Instance.OnMessage(WixVerboses.CreatingCabinetFiles()); 380 Messaging.Instance.OnMessage(WixVerboses.CreatingCabinetFiles());
398 381
@@ -400,7 +383,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
400 command.CabbingThreadCount = this.CabbingThreadCount; 383 command.CabbingThreadCount = this.CabbingThreadCount;
401 command.CabCachePath = this.CabCachePath; 384 command.CabCachePath = this.CabCachePath;
402 command.DefaultCompressionLevel = this.DefaultCompressionLevel; 385 command.DefaultCompressionLevel = this.DefaultCompressionLevel;
403 command.Output = this.Output; 386 command.Output = output;
404 command.BackendExtensions = this.BackendExtensions; 387 command.BackendExtensions = this.BackendExtensions;
405 command.LayoutDirectory = layoutDirectory; 388 command.LayoutDirectory = layoutDirectory;
406 command.Compressed = compressed; 389 command.Compressed = compressed;
@@ -408,39 +391,35 @@ namespace WixToolset.Core.WindowsInstaller.Bind
408 command.ResolveMedia = this.ResolveMedia; 391 command.ResolveMedia = this.ResolveMedia;
409 command.TableDefinitions = this.TableDefinitions; 392 command.TableDefinitions = this.TableDefinitions;
410 command.TempFilesLocation = this.IntermediateFolder; 393 command.TempFilesLocation = this.IntermediateFolder;
411 command.WixMediaTable = this.Output.Tables["WixMedia"]; 394 command.WixMediaTable = output.Tables["WixMedia"];
412 command.Execute(); 395 command.Execute();
413 396
414 fileTransfers.AddRange(command.FileTransfers); 397 fileTransfers.AddRange(command.FileTransfers);
415 } 398 }
416 399
400#if TODO_FINISH_PATCH
417 if (OutputType.Patch == this.Output.Type) 401 if (OutputType.Patch == this.Output.Type)
418 { 402 {
419 // copy output data back into the transforms 403 // copy output data back into the transforms
420 this.CopyToTransformData(this.Output); 404 this.CopyToTransformData(this.Output);
421 } 405 }
406#endif
422 407
423 // stop processing if an error previously occurred 408 // Add back suppressed tables which must be present prior to merging in modules.
424 if (Messaging.Instance.EncounteredError) 409 if (OutputType.Product == output.Type)
425 {
426 return;
427 }
428
429 // add back suppressed tables which must be present prior to merging in modules
430 if (OutputType.Product == this.Output.Type)
431 { 410 {
432 Table wixMergeTable = this.Output.Tables["WixMerge"]; 411 Table wixMergeTable = output.Tables["WixMerge"];
433 412
434 if (null != wixMergeTable && 0 < wixMergeTable.Rows.Count) 413 if (null != wixMergeTable && 0 < wixMergeTable.Rows.Count)
435 { 414 {
436 foreach (SequenceTable sequence in Enum.GetValues(typeof(SequenceTable))) 415 foreach (SequenceTable sequence in Enum.GetValues(typeof(SequenceTable)))
437 { 416 {
438 string sequenceTableName = sequence.ToString(); 417 string sequenceTableName = sequence.ToString();
439 Table sequenceTable = this.Output.Tables[sequenceTableName]; 418 Table sequenceTable = output.Tables[sequenceTableName];
440 419
441 if (null == sequenceTable) 420 if (null == sequenceTable)
442 { 421 {
443 sequenceTable = this.Output.EnsureTable(this.TableDefinitions[sequenceTableName]); 422 sequenceTable = output.EnsureTable(this.TableDefinitions[sequenceTableName]);
444 } 423 }
445 424
446 if (0 == sequenceTable.Rows.Count) 425 if (0 == sequenceTable.Rows.Count)
@@ -456,67 +435,59 @@ namespace WixToolset.Core.WindowsInstaller.Bind
456 // extension.PostBind(this.Context); 435 // extension.PostBind(this.Context);
457 //} 436 //}
458 437
459 // generate database file 438 this.ValidateComponentGuids(output);
439
440 // stop processing if an error previously occurred
441 if (Messaging.Instance.EncounteredError)
442 {
443 return;
444 }
445
446 // Generate database file.
460 Messaging.Instance.OnMessage(WixVerboses.GeneratingDatabase()); 447 Messaging.Instance.OnMessage(WixVerboses.GeneratingDatabase());
461 string tempDatabaseFile = Path.Combine(this.IntermediateFolder, Path.GetFileName(this.OutputPath)); 448 string tempDatabaseFile = Path.Combine(this.IntermediateFolder, Path.GetFileName(this.OutputPath));
462 this.GenerateDatabase(this.Output, tempDatabaseFile, false, false); 449 this.GenerateDatabase(output, tempDatabaseFile, false, false);
463 450
464 FileTransfer transfer; 451 if (FileTransfer.TryCreate(tempDatabaseFile, this.OutputPath, true, output.Type.ToString(), null, out var transfer)) // note where this database needs to move in the future
465 if (FileTransfer.TryCreate(tempDatabaseFile, this.OutputPath, true, this.Output.Type.ToString(), null, out transfer)) // note where this database needs to move in the future
466 { 452 {
467 transfer.Built = true; 453 transfer.Built = true;
468 fileTransfers.Add(transfer); 454 fileTransfers.Add(transfer);
469 } 455 }
470 456
471 // stop processing if an error previously occurred 457 // Stop processing if an error previously occurred.
472 if (Messaging.Instance.EncounteredError) 458 if (Messaging.Instance.EncounteredError)
473 { 459 {
474 return; 460 return;
475 } 461 }
476 462
477 // Output the output to a file 463 // Output the output to a file.
478 Pdb pdb = new Pdb(); 464 Pdb pdb = new Pdb();
479 pdb.Output = this.Output; 465 pdb.Output = output;
480 if (!String.IsNullOrEmpty(this.PdbFile)) 466 if (!String.IsNullOrEmpty(this.PdbFile))
481 { 467 {
482 pdb.Save(this.PdbFile); 468 pdb.Save(this.PdbFile);
483 } 469 }
484 470
485 // Merge modules. 471 // Merge modules.
486 if (OutputType.Product == this.Output.Type) 472 if (OutputType.Product == output.Type)
487 { 473 {
488 Messaging.Instance.OnMessage(WixVerboses.MergingModules()); 474 Messaging.Instance.OnMessage(WixVerboses.MergingModules());
489 475
490 MergeModulesCommand command = new MergeModulesCommand(); 476 var command = new MergeModulesCommand();
491 command.FileFacades = fileFacades; 477 command.FileFacades = fileFacades;
492 command.Output = this.Output; 478 command.Output = output;
493 command.OutputPath = tempDatabaseFile; 479 command.OutputPath = tempDatabaseFile;
494 command.SuppressedTableNames = suppressedTableNames; 480 command.SuppressedTableNames = suppressedTableNames;
495 command.Execute(); 481 command.Execute();
496
497 // stop processing if an error previously occurred
498 if (Messaging.Instance.EncounteredError)
499 {
500 return;
501 }
502 } 482 }
503 483
504 // inspect the MSI prior to running ICEs
505 //InspectorCore inspectorCore = new InspectorCore();
506 //foreach (InspectorExtension inspectorExtension in this.InspectorExtensions)
507 //{
508 // inspectorExtension.Core = inspectorCore;
509 // inspectorExtension.InspectDatabase(tempDatabaseFile, pdb);
510
511 // inspectorExtension.Core = null; // reset.
512 //}
513
514 if (Messaging.Instance.EncounteredError) 484 if (Messaging.Instance.EncounteredError)
515 { 485 {
516 return; 486 return;
517 } 487 }
518 488
519 // validate the output if there is an MSI validator 489#if TODO_FINISH_VALIDATION
490 // Validate the output if there is an MSI validator.
520 if (null != this.Validator) 491 if (null != this.Validator)
521 { 492 {
522 Stopwatch stopwatch = Stopwatch.StartNew(); 493 Stopwatch stopwatch = Stopwatch.StartNew();
@@ -537,19 +508,18 @@ namespace WixToolset.Core.WindowsInstaller.Bind
537 return; 508 return;
538 } 509 }
539 } 510 }
511#endif
540 512
541 // Process uncompressed files. 513 // Process uncompressed files.
542 if (!Messaging.Instance.EncounteredError && !this.SuppressLayout && uncompressedFiles.Any()) 514 if (!Messaging.Instance.EncounteredError && !this.SuppressLayout && uncompressedFiles.Any())
543 { 515 {
544 var command = new ProcessUncompressedFilesCommand(); 516 var command = new ProcessUncompressedFilesCommand(section);
545 command.Compressed = compressed; 517 command.Compressed = compressed;
546 command.FileFacades = uncompressedFiles; 518 command.FileFacades = uncompressedFiles;
547 command.LayoutDirectory = layoutDirectory; 519 command.LayoutDirectory = layoutDirectory;
548 command.LongNamesInImage = longNames; 520 command.LongNamesInImage = longNames;
549 command.MediaRows = assignedMediaRows;
550 command.ResolveMedia = this.ResolveMedia; 521 command.ResolveMedia = this.ResolveMedia;
551 command.DatabasePath = tempDatabaseFile; 522 command.DatabasePath = tempDatabaseFile;
552 command.WixMediaTable = this.Output.Tables["WixMedia"];
553 command.Execute(); 523 command.Execute();
554 524
555 fileTransfers.AddRange(command.FileTransfers); 525 fileTransfers.AddRange(command.FileTransfers);
@@ -557,94 +527,92 @@ namespace WixToolset.Core.WindowsInstaller.Bind
557 527
558 this.FileTransfers = fileTransfers; 528 this.FileTransfers = fileTransfers;
559 this.ContentFilePaths = fileFacades.Select(r => r.WixFile.Source).ToList(); 529 this.ContentFilePaths = fileFacades.Select(r => r.WixFile.Source).ToList();
530
531 // TODO: Eventually this gets removed
532 var intermediate = new Intermediate(this.Intermediate.Id, new[] { section }, this.Intermediate.Localizations.ToDictionary(l => l.Culture, StringComparer.OrdinalIgnoreCase), this.Intermediate.EmbedFilePaths);
533 intermediate.Save(Path.ChangeExtension(this.OutputPath, "wir"));
560 } 534 }
561 535
562 /// <summary> 536 /// <summary>
563 /// Localize dialogs and controls. 537 /// Localize dialogs and controls.
564 /// </summary> 538 /// </summary>
565 /// <param name="tables">The tables to localize.</param> 539 /// <param name="tables">The tables to localize.</param>
566 private void LocalizeUI(TableIndexedCollection tables) 540 private void LocalizeUI(IntermediateSection section)
567 { 541 {
568 Table dialogTable = tables["Dialog"]; 542 foreach (var row in section.Tuples.OfType<DialogTuple>())
569 if (null != dialogTable)
570 { 543 {
571 foreach (Row row in dialogTable.Rows) 544 string dialog = row.Dialog;
572 {
573 string dialog = (string)row[0];
574 545
575 if (this.WixVariableResolver.TryGetLocalizedControl(dialog, null, out LocalizedControl localizedControl)) 546 if (this.WixVariableResolver.TryGetLocalizedControl(dialog, null, out LocalizedControl localizedControl))
547 {
548 if (CompilerConstants.IntegerNotSet != localizedControl.X)
576 { 549 {
577 if (CompilerConstants.IntegerNotSet != localizedControl.X) 550 row.HCentering = localizedControl.X;
578 { 551 }
579 row[1] = localizedControl.X;
580 }
581 552
582 if (CompilerConstants.IntegerNotSet != localizedControl.Y) 553 if (CompilerConstants.IntegerNotSet != localizedControl.Y)
583 { 554 {
584 row[2] = localizedControl.Y; 555 row.VCentering = localizedControl.Y;
585 } 556 }
586 557
587 if (CompilerConstants.IntegerNotSet != localizedControl.Width) 558 if (CompilerConstants.IntegerNotSet != localizedControl.Width)
588 { 559 {
589 row[3] = localizedControl.Width; 560 row.Width = localizedControl.Width;
590 } 561 }
591 562
592 if (CompilerConstants.IntegerNotSet != localizedControl.Height) 563 if (CompilerConstants.IntegerNotSet != localizedControl.Height)
593 { 564 {
594 row[4] = localizedControl.Height; 565 row.Height = localizedControl.Height;
595 } 566 }
596 567
597 row[5] = (int)row[5] | localizedControl.Attributes; 568 row.Attributes = row.Attributes | localizedControl.Attributes;
598 569
599 if (!String.IsNullOrEmpty(localizedControl.Text)) 570 if (!String.IsNullOrEmpty(localizedControl.Text))
600 { 571 {
601 row[6] = localizedControl.Text; 572 row.Title = localizedControl.Text;
602 }
603 } 573 }
604 } 574 }
605 } 575 }
606 576
607 Table controlTable = tables["Control"]; 577
608 if (null != controlTable) 578 foreach (var row in section.Tuples.OfType<ControlTuple>())
609 { 579 {
610 foreach (Row row in controlTable.Rows) 580 string dialog = row.Dialog_;
611 { 581 string control = row.Control;
612 string dialog = (string)row[0];
613 string control = (string)row[1];
614 582
615 if (this.WixVariableResolver.TryGetLocalizedControl(dialog, control, out LocalizedControl localizedControl)) 583 if (this.WixVariableResolver.TryGetLocalizedControl(dialog, control, out LocalizedControl localizedControl))
584 {
585 if (CompilerConstants.IntegerNotSet != localizedControl.X)
616 { 586 {
617 if (CompilerConstants.IntegerNotSet != localizedControl.X) 587 row.X = localizedControl.X;
618 { 588 }
619 row[3] = localizedControl.X.ToString();
620 }
621 589
622 if (CompilerConstants.IntegerNotSet != localizedControl.Y) 590 if (CompilerConstants.IntegerNotSet != localizedControl.Y)
623 { 591 {
624 row[4] = localizedControl.Y.ToString(); 592 row.Y = localizedControl.Y;
625 } 593 }
626 594
627 if (CompilerConstants.IntegerNotSet != localizedControl.Width) 595 if (CompilerConstants.IntegerNotSet != localizedControl.Width)
628 { 596 {
629 row[5] = localizedControl.Width.ToString(); 597 row.Width = localizedControl.Width;
630 } 598 }
631 599
632 if (CompilerConstants.IntegerNotSet != localizedControl.Height) 600 if (CompilerConstants.IntegerNotSet != localizedControl.Height)
633 { 601 {
634 row[6] = localizedControl.Height.ToString(); 602 row.Height = localizedControl.Height;
635 } 603 }
636 604
637 row[7] = (int)row[7] | localizedControl.Attributes; 605 row.Attributes = row.Attributes | localizedControl.Attributes;
638 606
639 if (!String.IsNullOrEmpty(localizedControl.Text)) 607 if (!String.IsNullOrEmpty(localizedControl.Text))
640 { 608 {
641 row[9] = localizedControl.Text; 609 row.Text = localizedControl.Text;
642 }
643 } 610 }
644 } 611 }
645 } 612 }
646 } 613 }
647 614
615#if TODO_FINISH_PATCH
648 /// <summary> 616 /// <summary>
649 /// Copy file data between transform substorages and the patch output object 617 /// Copy file data between transform substorages and the patch output object
650 /// </summary> 618 /// </summary>
@@ -674,269 +642,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind
674 command.TableDefinitions = this.TableDefinitions; 642 command.TableDefinitions = this.TableDefinitions;
675 command.Execute(); 643 command.Execute();
676 } 644 }
645#endif
677 646
678 private void UpdateMediaSequences(OutputType outputType, IEnumerable<FileFacade> fileFacades, RowDictionary<MediaRow> mediaRows)
679 {
680 // Calculate sequence numbers and media disk id layout for all file media information objects.
681 if (OutputType.Module == outputType)
682 {
683 int lastSequence = 0;
684 foreach (FileFacade facade in fileFacades) // TODO: Sort these rows directory path and component id and maybe file size or file extension and other creative ideas to get optimal install speed out of MSI.
685 {
686 facade.File.Sequence = ++lastSequence;
687 }
688 }
689 else
690 {
691 int lastSequence = 0;
692 MediaRow mediaRow = null;
693 Dictionary<int, List<FileFacade>> patchGroups = new Dictionary<int, List<FileFacade>>();
694
695 // sequence the non-patch-added files
696 foreach (FileFacade facade in fileFacades) // TODO: Sort these rows directory path and component id and maybe file size or file extension and other creative ideas to get optimal install speed out of MSI.
697 {
698 if (null == mediaRow)
699 {
700 mediaRow = mediaRows.Get(facade.WixFile.DiskId);
701 if (OutputType.Patch == outputType)
702 {
703 // patch Media cannot start at zero
704 lastSequence = mediaRow.LastSequence;
705 }
706 }
707 else if (mediaRow.DiskId != facade.WixFile.DiskId)
708 {
709 mediaRow.LastSequence = lastSequence;
710 mediaRow = mediaRows.Get(facade.WixFile.DiskId);
711 }
712
713 if (0 < facade.WixFile.PatchGroup)
714 {
715 List<FileFacade> patchGroup = patchGroups[facade.WixFile.PatchGroup];
716
717 if (null == patchGroup)
718 {
719 patchGroup = new List<FileFacade>();
720 patchGroups.Add(facade.WixFile.PatchGroup, patchGroup);
721 }
722
723 patchGroup.Add(facade);
724 }
725 else
726 {
727 facade.File.Sequence = ++lastSequence;
728 }
729 }
730
731 if (null != mediaRow)
732 {
733 mediaRow.LastSequence = lastSequence;
734 mediaRow = null;
735 }
736
737 // sequence the patch-added files
738 foreach (List<FileFacade> patchGroup in patchGroups.Values)
739 {
740 foreach (FileFacade facade in patchGroup)
741 {
742 if (null == mediaRow)
743 {
744 mediaRow = mediaRows.Get(facade.WixFile.DiskId);
745 }
746 else if (mediaRow.DiskId != facade.WixFile.DiskId)
747 {
748 mediaRow.LastSequence = lastSequence;
749 mediaRow = mediaRows.Get(facade.WixFile.DiskId);
750 }
751
752 facade.File.Sequence = ++lastSequence;
753 }
754 }
755
756 if (null != mediaRow)
757 {
758 mediaRow.LastSequence = lastSequence;
759 }
760 }
761 }
762
763 /// <summary>
764 /// Set the guids for components with generatable guids.
765 /// </summary>
766 /// <param name="output">Internal representation of the database to operate on.</param>
767 private void SetComponentGuids(Output output)
768 {
769 Table componentTable = output.Tables["Component"];
770 if (null != componentTable)
771 {
772 Hashtable registryKeyRows = null;
773 Hashtable directories = null;
774 Hashtable componentIdGenSeeds = null;
775 Dictionary<string, List<FileRow>> fileRows = null;
776
777 // find components with generatable guids
778 foreach (ComponentRow componentRow in componentTable.Rows)
779 {
780 // component guid will be generated
781 if ("*" == componentRow.Guid)
782 {
783 if (null == componentRow.KeyPath || componentRow.IsOdbcDataSourceKeyPath)
784 {
785 Messaging.Instance.OnMessage(WixErrors.IllegalComponentWithAutoGeneratedGuid(componentRow.SourceLineNumbers));
786 }
787 else if (componentRow.IsRegistryKeyPath)
788 {
789 if (null == registryKeyRows)
790 {
791 Table registryTable = output.Tables["Registry"];
792
793 registryKeyRows = new Hashtable(registryTable.Rows.Count);
794
795 foreach (Row registryRow in registryTable.Rows)
796 {
797 registryKeyRows.Add((string)registryRow[0], registryRow);
798 }
799 }
800
801 Row foundRow = registryKeyRows[componentRow.KeyPath] as Row;
802
803 string bitness = componentRow.Is64Bit ? "64" : String.Empty;
804 if (null != foundRow)
805 {
806 string regkey = String.Concat(bitness, foundRow[1], "\\", foundRow[2], "\\", foundRow[3]);
807 componentRow.Guid = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, regkey.ToLowerInvariant()).ToString("B").ToUpperInvariant();
808 }
809 }
810 else // must be a File KeyPath
811 {
812 // if the directory table hasn't been loaded into an indexed hash
813 // of directory ids to target names do that now.
814 if (null == directories)
815 {
816 Table directoryTable = output.Tables["Directory"];
817
818 int numDirectoryTableRows = (null != directoryTable) ? directoryTable.Rows.Count : 0;
819
820 directories = new Hashtable(numDirectoryTableRows);
821
822 // get the target paths for all directories
823 if (null != directoryTable)
824 {
825 foreach (Row row in directoryTable.Rows)
826 {
827 // if the directory Id already exists, we will skip it here since
828 // checking for duplicate primary keys is done later when importing tables
829 // into database
830 if (directories.ContainsKey(row[0]))
831 {
832 continue;
833 }
834
835 string targetName = Common.GetName((string)row[2], false, true);
836 directories.Add(row[0], new ResolvedDirectory((string)row[1], targetName));
837 }
838 }
839 }
840
841 // if the component id generation seeds have not been indexed
842 // from the WixDirectory table do that now.
843 if (null == componentIdGenSeeds)
844 {
845 Table wixDirectoryTable = output.Tables["WixDirectory"];
846
847 int numWixDirectoryRows = (null != wixDirectoryTable) ? wixDirectoryTable.Rows.Count : 0;
848
849 componentIdGenSeeds = new Hashtable(numWixDirectoryRows);
850
851 // if there are any WixDirectory rows, build up the Component Guid
852 // generation seeds indexed by Directory/@Id.
853 if (null != wixDirectoryTable)
854 {
855 foreach (Row row in wixDirectoryTable.Rows)
856 {
857 componentIdGenSeeds.Add(row[0], (string)row[1]);
858 }
859 }
860 }
861
862 // if the file rows have not been indexed by File.Component yet
863 // then do that now
864 if (null == fileRows)
865 {
866 Table fileTable = output.Tables["File"];
867
868 int numFileRows = (null != fileTable) ? fileTable.Rows.Count : 0;
869
870 fileRows = new Dictionary<string, List<FileRow>>(numFileRows);
871
872 if (null != fileTable)
873 {
874 foreach (FileRow file in fileTable.Rows)
875 {
876 List<FileRow> files;
877 if (!fileRows.TryGetValue(file.Component, out files))
878 {
879 files = new List<FileRow>();
880 fileRows.Add(file.Component, files);
881 }
882
883 files.Add(file);
884 }
885 }
886 }
887
888 // validate component meets all the conditions to have a generated guid
889 List<FileRow> currentComponentFiles = fileRows[componentRow.Component];
890 int numFilesInComponent = currentComponentFiles.Count;
891 string path = null;
892
893 foreach (FileRow fileRow in currentComponentFiles)
894 {
895 if (fileRow.File == componentRow.KeyPath)
896 {
897 // calculate the key file's canonical target path
898 string directoryPath = Binder.GetDirectoryPath(directories, componentIdGenSeeds, componentRow.Directory, true);
899 string fileName = Common.GetName(fileRow.FileName, false, true).ToLower(CultureInfo.InvariantCulture);
900 path = Path.Combine(directoryPath, fileName);
901
902 // find paths that are not canonicalized
903 if (path.StartsWith(@"PersonalFolder\my pictures", StringComparison.Ordinal) ||
904 path.StartsWith(@"ProgramFilesFolder\common files", StringComparison.Ordinal) ||
905 path.StartsWith(@"ProgramMenuFolder\startup", StringComparison.Ordinal) ||
906 path.StartsWith("TARGETDIR", StringComparison.Ordinal) ||
907 path.StartsWith(@"StartMenuFolder\programs", StringComparison.Ordinal) ||
908 path.StartsWith(@"WindowsFolder\fonts", StringComparison.Ordinal))
909 {
910 Messaging.Instance.OnMessage(WixErrors.IllegalPathForGeneratedComponentGuid(componentRow.SourceLineNumbers, fileRow.Component, path));
911 }
912
913 // if component has more than one file, the key path must be versioned
914 if (1 < numFilesInComponent && String.IsNullOrEmpty(fileRow.Version))
915 {
916 Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentUnversionedKeypath(componentRow.SourceLineNumbers));
917 }
918 }
919 else
920 {
921 // not a key path, so it must be an unversioned file if component has more than one file
922 if (1 < numFilesInComponent && !String.IsNullOrEmpty(fileRow.Version))
923 {
924 Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentVersionedNonkeypath(componentRow.SourceLineNumbers));
925 }
926 }
927 }
928
929 // if the rules were followed, reward with a generated guid
930 if (!Messaging.Instance.EncounteredError)
931 {
932 componentRow.Guid = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, path).ToString("B").ToUpperInvariant();
933 }
934 }
935 }
936 }
937 }
938 }
939 647
648#if TODO_FIX_INSTANCE_TRANSFORM
940 /// <summary> 649 /// <summary>
941 /// Creates instance transform substorages in the output. 650 /// Creates instance transform substorages in the output.
942 /// </summary> 651 /// </summary>
@@ -1171,6 +880,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
1171 } 880 }
1172 } 881 }
1173 } 882 }
883#endif
1174 884
1175 /// <summary> 885 /// <summary>
1176 /// Validate that there are no duplicate GUIDs in the output. 886 /// Validate that there are no duplicate GUIDs in the output.
@@ -1186,7 +896,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
1186 { 896 {
1187 Dictionary<string, bool> componentGuidConditions = new Dictionary<string, bool>(componentTable.Rows.Count); 897 Dictionary<string, bool> componentGuidConditions = new Dictionary<string, bool>(componentTable.Rows.Count);
1188 898
1189 foreach (ComponentRow row in componentTable.Rows) 899 foreach (Data.Rows.ComponentRow row in componentTable.Rows)
1190 { 900 {
1191 // we don't care about unmanaged components and if there's a * GUID remaining, 901 // we don't care about unmanaged components and if there's a * GUID remaining,
1192 // there's already an error that prevented it from being replaced with a real GUID. 902 // there's already an error that prevented it from being replaced with a real GUID.
@@ -1221,7 +931,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
1221 /// <param name="output">Internal representation of the msi database to operate upon.</param> 931 /// <param name="output">Internal representation of the msi database to operate upon.</param>
1222 private void UpdateControlText(Output output) 932 private void UpdateControlText(Output output)
1223 { 933 {
1224 UpdateControlTextCommand command = new UpdateControlTextCommand(); 934 var command = new UpdateControlTextCommand();
1225 command.BBControlTable = output.Tables["BBControl"]; 935 command.BBControlTable = output.Tables["BBControl"];
1226 command.WixBBControlTable = output.Tables["WixBBControl"]; 936 command.WixBBControlTable = output.Tables["WixBBControl"];
1227 command.ControlTable = output.Tables["Control"]; 937 command.ControlTable = output.Tables["Control"];
@@ -1229,7 +939,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
1229 command.Execute(); 939 command.Execute();
1230 } 940 }
1231 941
1232 private string ResolveMedia(MediaRow mediaRow, string mediaLayoutDirectory, string layoutDirectory) 942 private string ResolveMedia(MediaTuple mediaRow, string mediaLayoutDirectory, string layoutDirectory)
1233 { 943 {
1234 string layout = null; 944 string layout = null;
1235 945
@@ -1282,7 +992,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
1282 command.TempFilesLocation = this.IntermediateFolder; 992 command.TempFilesLocation = this.IntermediateFolder;
1283 command.Codepage = this.Codepage; 993 command.Codepage = this.Codepage;
1284 command.Execute(); 994 command.Execute();
1285#endif
1286 } 995 }
1287 } 996 }
1288} 997}