aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-04-13 10:14:16 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-04-13 13:13:48 -0500
commit3704a5547766581b15690b6535d03568afcfc2a0 (patch)
treebf8c7fefd5ec6a9a6dd9c998c54758bb751c44a8 /src
parent863c1b8180d802f98e37be876b0c27efce2e8ace (diff)
downloadwix-3704a5547766581b15690b6535d03568afcfc2a0.tar.gz
wix-3704a5547766581b15690b6535d03568afcfc2a0.tar.bz2
wix-3704a5547766581b15690b6535d03568afcfc2a0.zip
Change harvested symbols to ref the package payload for remote support.
Diffstat (limited to 'src')
-rw-r--r--src/api/wix/WixToolset.Data/Symbols/SymbolDefinitions.cs4
-rw-r--r--src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedDependencyProviderSymbol.cs93
-rw-r--r--src/api/wix/WixToolset.Data/Symbols/WixBundleMsiFeatureSymbol.cs10
-rw-r--r--src/api/wix/WixToolset.Data/Symbols/WixBundlePackageRelatedBundleSymbol.cs10
-rw-r--r--src/api/wix/WixToolset.Data/Symbols/WixBundlePatchTargetCodeSymbol.cs10
-rw-r--r--src/api/wix/WixToolset.Data/Symbols/WixBundleRelatedPackageSymbol.cs10
-rw-r--r--src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs20
-rw-r--r--src/wix/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs1
-rw-r--r--src/wix/WixToolset.Core.Burn/Bind/ProcessDependencyProvidersCommand.cs49
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/AutomaticallySlipstreamPatchesCommand.cs39
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/CreateBootstrapperApplicationManifestCommand.cs61
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs49
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/GetPackageFacadesCommand.cs15
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/OrderPackagesAndRollbackBoundariesCommand.cs14
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/PackageFacades.cs54
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/PerformBundleBackendValidationCommand.cs9
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs15
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs51
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs6
-rw-r--r--src/wix/WixToolset.Core.Burn/BurnBackendErrors.cs6
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/PackagePayloadFixture.cs78
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/TestData/PackagePayload/MsiPackagePayloadInPayloadGroup.wxs18
22 files changed, 461 insertions, 161 deletions
diff --git a/src/api/wix/WixToolset.Data/Symbols/SymbolDefinitions.cs b/src/api/wix/WixToolset.Data/Symbols/SymbolDefinitions.cs
index 3e0ec512..4a3269c5 100644
--- a/src/api/wix/WixToolset.Data/Symbols/SymbolDefinitions.cs
+++ b/src/api/wix/WixToolset.Data/Symbols/SymbolDefinitions.cs
@@ -131,6 +131,7 @@ namespace WixToolset.Data
131 WixBundleExePackagePayload, 131 WixBundleExePackagePayload,
132 WixBundleExtension, 132 WixBundleExtension,
133 WixBundleHarvestedBundlePackage, 133 WixBundleHarvestedBundlePackage,
134 WixBundleHarvestedDependencyProvider,
134 WixBundleHarvestedMsiPackage, 135 WixBundleHarvestedMsiPackage,
135 WixBundleHarvestedMspPackage, 136 WixBundleHarvestedMspPackage,
136 WixBundleMsiFeature, 137 WixBundleMsiFeature,
@@ -589,6 +590,9 @@ namespace WixToolset.Data
589 case SymbolDefinitionType.WixBundleHarvestedBundlePackage: 590 case SymbolDefinitionType.WixBundleHarvestedBundlePackage:
590 return SymbolDefinitions.WixBundleHarvestedBundlePackage; 591 return SymbolDefinitions.WixBundleHarvestedBundlePackage;
591 592
593 case SymbolDefinitionType.WixBundleHarvestedDependencyProvider:
594 return SymbolDefinitions.WixBundleHarvestedDependencyProvider;
595
592 case SymbolDefinitionType.WixBundleHarvestedMsiPackage: 596 case SymbolDefinitionType.WixBundleHarvestedMsiPackage:
593 return SymbolDefinitions.WixBundleHarvestedMsiPackage; 597 return SymbolDefinitions.WixBundleHarvestedMsiPackage;
594 598
diff --git a/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedDependencyProviderSymbol.cs b/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedDependencyProviderSymbol.cs
new file mode 100644
index 00000000..71d77c94
--- /dev/null
+++ b/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedDependencyProviderSymbol.cs
@@ -0,0 +1,93 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Data
4{
5 using WixToolset.Data.Symbols;
6
7 public static partial class SymbolDefinitions
8 {
9 public static readonly IntermediateSymbolDefinition WixBundleHarvestedDependencyProvider = new IntermediateSymbolDefinition(
10 SymbolDefinitionType.WixBundleHarvestedDependencyProvider,
11 new[]
12 {
13 new IntermediateFieldDefinition(nameof(WixBundleHarvestedDependencyProviderSymbolFields.PackagePayloadRef), IntermediateFieldType.String),
14 new IntermediateFieldDefinition(nameof(WixBundleHarvestedDependencyProviderSymbolFields.Attributes), IntermediateFieldType.Number),
15 new IntermediateFieldDefinition(nameof(WixBundleHarvestedDependencyProviderSymbolFields.ProviderKey), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(WixBundleHarvestedDependencyProviderSymbolFields.Version), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(WixBundleHarvestedDependencyProviderSymbolFields.DisplayName), IntermediateFieldType.String),
18 new IntermediateFieldDefinition(nameof(WixBundleHarvestedDependencyProviderSymbolFields.ProviderAttributes), IntermediateFieldType.Number),
19 },
20 typeof(WixDependencyProviderSymbol));
21 }
22}
23
24namespace WixToolset.Data.Symbols
25{
26 using System;
27 using WixToolset.Data;
28
29 public enum WixBundleHarvestedDependencyProviderSymbolFields
30 {
31 PackagePayloadRef,
32 Attributes,
33 ProviderKey,
34 Version,
35 DisplayName,
36 ProviderAttributes,
37 }
38
39 [Flags]
40 public enum WixBundleHarvestedDependencyProviderAttributes
41 {
42 None = 0x0,
43 }
44
45 public class WixBundleHarvestedDependencyProviderSymbol : IntermediateSymbol
46 {
47 public WixBundleHarvestedDependencyProviderSymbol() : base(SymbolDefinitions.WixBundleHarvestedDependencyProvider, null, null)
48 {
49 }
50
51 public WixBundleHarvestedDependencyProviderSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(SymbolDefinitions.WixBundleHarvestedDependencyProvider, sourceLineNumber, id)
52 {
53 }
54
55 public IntermediateField this[WixBundleHarvestedDependencyProviderSymbolFields index] => this.Fields[(int)index];
56
57 public string PackagePayloadRef
58 {
59 get => this.Fields[(int)WixBundleHarvestedDependencyProviderSymbolFields.PackagePayloadRef].AsString();
60 set => this.Set((int)WixBundleHarvestedDependencyProviderSymbolFields.PackagePayloadRef, value);
61 }
62
63 public WixBundleHarvestedDependencyProviderAttributes Attributes
64 {
65 get => (WixBundleHarvestedDependencyProviderAttributes)this.Fields[(int)WixBundleHarvestedDependencyProviderSymbolFields.Attributes].AsNumber();
66 set => this.Set((int)WixBundleHarvestedDependencyProviderSymbolFields.Attributes, (int)value);
67 }
68
69 public string ProviderKey
70 {
71 get => this.Fields[(int)WixBundleHarvestedDependencyProviderSymbolFields.ProviderKey].AsString();
72 set => this.Set((int)WixBundleHarvestedDependencyProviderSymbolFields.ProviderKey, value);
73 }
74
75 public string Version
76 {
77 get => this.Fields[(int)WixBundleHarvestedDependencyProviderSymbolFields.Version].AsString();
78 set => this.Set((int)WixBundleHarvestedDependencyProviderSymbolFields.Version, value);
79 }
80
81 public string DisplayName
82 {
83 get => this.Fields[(int)WixBundleHarvestedDependencyProviderSymbolFields.DisplayName].AsString();
84 set => this.Set((int)WixBundleHarvestedDependencyProviderSymbolFields.DisplayName, value);
85 }
86
87 public int ProviderAttributes
88 {
89 get => this.Fields[(int)WixBundleHarvestedDependencyProviderSymbolFields.ProviderAttributes].AsNumber();
90 set => this.Set((int)WixBundleHarvestedDependencyProviderSymbolFields.ProviderAttributes, value);
91 }
92 }
93}
diff --git a/src/api/wix/WixToolset.Data/Symbols/WixBundleMsiFeatureSymbol.cs b/src/api/wix/WixToolset.Data/Symbols/WixBundleMsiFeatureSymbol.cs
index 829e81c0..86ebdeb8 100644
--- a/src/api/wix/WixToolset.Data/Symbols/WixBundleMsiFeatureSymbol.cs
+++ b/src/api/wix/WixToolset.Data/Symbols/WixBundleMsiFeatureSymbol.cs
@@ -10,7 +10,7 @@ namespace WixToolset.Data
10 SymbolDefinitionType.WixBundleMsiFeature, 10 SymbolDefinitionType.WixBundleMsiFeature,
11 new[] 11 new[]
12 { 12 {
13 new IntermediateFieldDefinition(nameof(WixBundleMsiFeatureSymbolFields.PackageRef), IntermediateFieldType.String), 13 new IntermediateFieldDefinition(nameof(WixBundleMsiFeatureSymbolFields.PackagePayloadRef), IntermediateFieldType.String),
14 new IntermediateFieldDefinition(nameof(WixBundleMsiFeatureSymbolFields.Name), IntermediateFieldType.String), 14 new IntermediateFieldDefinition(nameof(WixBundleMsiFeatureSymbolFields.Name), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(WixBundleMsiFeatureSymbolFields.Size), IntermediateFieldType.LargeNumber), 15 new IntermediateFieldDefinition(nameof(WixBundleMsiFeatureSymbolFields.Size), IntermediateFieldType.LargeNumber),
16 new IntermediateFieldDefinition(nameof(WixBundleMsiFeatureSymbolFields.Parent), IntermediateFieldType.String), 16 new IntermediateFieldDefinition(nameof(WixBundleMsiFeatureSymbolFields.Parent), IntermediateFieldType.String),
@@ -29,7 +29,7 @@ namespace WixToolset.Data.Symbols
29{ 29{
30 public enum WixBundleMsiFeatureSymbolFields 30 public enum WixBundleMsiFeatureSymbolFields
31 { 31 {
32 PackageRef, 32 PackagePayloadRef,
33 Name, 33 Name,
34 Size, 34 Size,
35 Parent, 35 Parent,
@@ -53,10 +53,10 @@ namespace WixToolset.Data.Symbols
53 53
54 public IntermediateField this[WixBundleMsiFeatureSymbolFields index] => this.Fields[(int)index]; 54 public IntermediateField this[WixBundleMsiFeatureSymbolFields index] => this.Fields[(int)index];
55 55
56 public string PackageRef 56 public string PackagePayloadRef
57 { 57 {
58 get => (string)this.Fields[(int)WixBundleMsiFeatureSymbolFields.PackageRef]; 58 get => (string)this.Fields[(int)WixBundleMsiFeatureSymbolFields.PackagePayloadRef];
59 set => this.Set((int)WixBundleMsiFeatureSymbolFields.PackageRef, value); 59 set => this.Set((int)WixBundleMsiFeatureSymbolFields.PackagePayloadRef, value);
60 } 60 }
61 61
62 public string Name 62 public string Name
diff --git a/src/api/wix/WixToolset.Data/Symbols/WixBundlePackageRelatedBundleSymbol.cs b/src/api/wix/WixToolset.Data/Symbols/WixBundlePackageRelatedBundleSymbol.cs
index dfb48714..31f4f713 100644
--- a/src/api/wix/WixToolset.Data/Symbols/WixBundlePackageRelatedBundleSymbol.cs
+++ b/src/api/wix/WixToolset.Data/Symbols/WixBundlePackageRelatedBundleSymbol.cs
@@ -10,7 +10,7 @@ namespace WixToolset.Data
10 SymbolDefinitionType.WixBundlePackageRelatedBundle, 10 SymbolDefinitionType.WixBundlePackageRelatedBundle,
11 new[] 11 new[]
12 { 12 {
13 new IntermediateFieldDefinition(nameof(WixBundlePackageRelatedBundleSymbolFields.PackageRef), IntermediateFieldType.String), 13 new IntermediateFieldDefinition(nameof(WixBundlePackageRelatedBundleSymbolFields.PackagePayloadRef), IntermediateFieldType.String),
14 new IntermediateFieldDefinition(nameof(WixBundlePackageRelatedBundleSymbolFields.BundleId), IntermediateFieldType.String), 14 new IntermediateFieldDefinition(nameof(WixBundlePackageRelatedBundleSymbolFields.BundleId), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(WixBundlePackageRelatedBundleSymbolFields.Action), IntermediateFieldType.Number), 15 new IntermediateFieldDefinition(nameof(WixBundlePackageRelatedBundleSymbolFields.Action), IntermediateFieldType.Number),
16 }, 16 },
@@ -22,7 +22,7 @@ namespace WixToolset.Data.Symbols
22{ 22{
23 public enum WixBundlePackageRelatedBundleSymbolFields 23 public enum WixBundlePackageRelatedBundleSymbolFields
24 { 24 {
25 PackageRef, 25 PackagePayloadRef,
26 BundleId, 26 BundleId,
27 Action, 27 Action,
28 } 28 }
@@ -39,10 +39,10 @@ namespace WixToolset.Data.Symbols
39 39
40 public IntermediateField this[WixBundlePackageRelatedBundleSymbolFields index] => this.Fields[(int)index]; 40 public IntermediateField this[WixBundlePackageRelatedBundleSymbolFields index] => this.Fields[(int)index];
41 41
42 public string PackageRef 42 public string PackagePayloadRef
43 { 43 {
44 get => (string)this.Fields[(int)WixBundlePackageRelatedBundleSymbolFields.PackageRef]; 44 get => (string)this.Fields[(int)WixBundlePackageRelatedBundleSymbolFields.PackagePayloadRef];
45 set => this.Set((int)WixBundlePackageRelatedBundleSymbolFields.PackageRef, value); 45 set => this.Set((int)WixBundlePackageRelatedBundleSymbolFields.PackagePayloadRef, value);
46 } 46 }
47 47
48 public string BundleId 48 public string BundleId
diff --git a/src/api/wix/WixToolset.Data/Symbols/WixBundlePatchTargetCodeSymbol.cs b/src/api/wix/WixToolset.Data/Symbols/WixBundlePatchTargetCodeSymbol.cs
index 85f50602..37b5bfa9 100644
--- a/src/api/wix/WixToolset.Data/Symbols/WixBundlePatchTargetCodeSymbol.cs
+++ b/src/api/wix/WixToolset.Data/Symbols/WixBundlePatchTargetCodeSymbol.cs
@@ -10,7 +10,7 @@ namespace WixToolset.Data
10 SymbolDefinitionType.WixBundlePatchTargetCode, 10 SymbolDefinitionType.WixBundlePatchTargetCode,
11 new[] 11 new[]
12 { 12 {
13 new IntermediateFieldDefinition(nameof(WixBundlePatchTargetCodeSymbolFields.PackageRef), IntermediateFieldType.String), 13 new IntermediateFieldDefinition(nameof(WixBundlePatchTargetCodeSymbolFields.PackagePayloadRef), IntermediateFieldType.String),
14 new IntermediateFieldDefinition(nameof(WixBundlePatchTargetCodeSymbolFields.TargetCode), IntermediateFieldType.String), 14 new IntermediateFieldDefinition(nameof(WixBundlePatchTargetCodeSymbolFields.TargetCode), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(WixBundlePatchTargetCodeSymbolFields.Attributes), IntermediateFieldType.Number), 15 new IntermediateFieldDefinition(nameof(WixBundlePatchTargetCodeSymbolFields.Attributes), IntermediateFieldType.Number),
16 new IntermediateFieldDefinition(nameof(WixBundlePatchTargetCodeSymbolFields.Type), IntermediateFieldType.Number), 16 new IntermediateFieldDefinition(nameof(WixBundlePatchTargetCodeSymbolFields.Type), IntermediateFieldType.Number),
@@ -25,7 +25,7 @@ namespace WixToolset.Data.Symbols
25 25
26 public enum WixBundlePatchTargetCodeSymbolFields 26 public enum WixBundlePatchTargetCodeSymbolFields
27 { 27 {
28 PackageRef, 28 PackagePayloadRef,
29 TargetCode, 29 TargetCode,
30 Attributes, 30 Attributes,
31 Type, 31 Type,
@@ -67,10 +67,10 @@ namespace WixToolset.Data.Symbols
67 67
68 public IntermediateField this[WixBundlePatchTargetCodeSymbolFields index] => this.Fields[(int)index]; 68 public IntermediateField this[WixBundlePatchTargetCodeSymbolFields index] => this.Fields[(int)index];
69 69
70 public string PackageRef 70 public string PackagePayloadRef
71 { 71 {
72 get => (string)this.Fields[(int)WixBundlePatchTargetCodeSymbolFields.PackageRef]; 72 get => (string)this.Fields[(int)WixBundlePatchTargetCodeSymbolFields.PackagePayloadRef];
73 set => this.Set((int)WixBundlePatchTargetCodeSymbolFields.PackageRef, value); 73 set => this.Set((int)WixBundlePatchTargetCodeSymbolFields.PackagePayloadRef, value);
74 } 74 }
75 75
76 public string TargetCode 76 public string TargetCode
diff --git a/src/api/wix/WixToolset.Data/Symbols/WixBundleRelatedPackageSymbol.cs b/src/api/wix/WixToolset.Data/Symbols/WixBundleRelatedPackageSymbol.cs
index 77789048..d809e09d 100644
--- a/src/api/wix/WixToolset.Data/Symbols/WixBundleRelatedPackageSymbol.cs
+++ b/src/api/wix/WixToolset.Data/Symbols/WixBundleRelatedPackageSymbol.cs
@@ -10,7 +10,7 @@ namespace WixToolset.Data
10 SymbolDefinitionType.WixBundleRelatedPackage, 10 SymbolDefinitionType.WixBundleRelatedPackage,
11 new[] 11 new[]
12 { 12 {
13 new IntermediateFieldDefinition(nameof(WixBundleRelatedPackageSymbolFields.PackageRef), IntermediateFieldType.String), 13 new IntermediateFieldDefinition(nameof(WixBundleRelatedPackageSymbolFields.PackagePayloadRef), IntermediateFieldType.String),
14 new IntermediateFieldDefinition(nameof(WixBundleRelatedPackageSymbolFields.RelatedId), IntermediateFieldType.String), 14 new IntermediateFieldDefinition(nameof(WixBundleRelatedPackageSymbolFields.RelatedId), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(WixBundleRelatedPackageSymbolFields.MinVersion), IntermediateFieldType.String), 15 new IntermediateFieldDefinition(nameof(WixBundleRelatedPackageSymbolFields.MinVersion), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(WixBundleRelatedPackageSymbolFields.MaxVersion), IntermediateFieldType.String), 16 new IntermediateFieldDefinition(nameof(WixBundleRelatedPackageSymbolFields.MaxVersion), IntermediateFieldType.String),
@@ -27,7 +27,7 @@ namespace WixToolset.Data.Symbols
27 27
28 public enum WixBundleRelatedPackageSymbolFields 28 public enum WixBundleRelatedPackageSymbolFields
29 { 29 {
30 PackageRef, 30 PackagePayloadRef,
31 RelatedId, 31 RelatedId,
32 MinVersion, 32 MinVersion,
33 MaxVersion, 33 MaxVersion,
@@ -57,10 +57,10 @@ namespace WixToolset.Data.Symbols
57 57
58 public IntermediateField this[WixBundleRelatedPackageSymbolFields index] => this.Fields[(int)index]; 58 public IntermediateField this[WixBundleRelatedPackageSymbolFields index] => this.Fields[(int)index];
59 59
60 public string PackageRef 60 public string PackagePayloadRef
61 { 61 {
62 get => (string)this.Fields[(int)WixBundleRelatedPackageSymbolFields.PackageRef]; 62 get => (string)this.Fields[(int)WixBundleRelatedPackageSymbolFields.PackagePayloadRef];
63 set => this.Set((int)WixBundleRelatedPackageSymbolFields.PackageRef, value); 63 set => this.Set((int)WixBundleRelatedPackageSymbolFields.PackagePayloadRef, value);
64 } 64 }
65 65
66 public string RelatedId 66 public string RelatedId
diff --git a/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs b/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
index 201d2839..ffc219dc 100644
--- a/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
@@ -159,7 +159,7 @@ namespace WixToolset.Core.Burn
159 processedPayloads = new HashSet<string>(payloadSymbols.Keys); 159 processedPayloads = new HashSet<string>(payloadSymbols.Keys);
160 } 160 }
161 161
162 IDictionary<string, PackageFacade> facades; 162 PackageFacades facades;
163 { 163 {
164 var command = new GetPackageFacadesCommand(this.Messaging, chainPackageSymbols, section); 164 var command = new GetPackageFacadesCommand(this.Messaging, chainPackageSymbols, section);
165 command.Execute(); 165 command.Execute();
@@ -325,7 +325,7 @@ namespace WixToolset.Core.Burn
325 325
326 // Determine patches to automatically slipstream. 326 // Determine patches to automatically slipstream.
327 { 327 {
328 var command = new AutomaticallySlipstreamPatchesCommand(section, facades.Values); 328 var command = new AutomaticallySlipstreamPatchesCommand(this.Messaging, section, facades);
329 command.Execute(); 329 command.Execute();
330 } 330 }
331 331
@@ -334,13 +334,11 @@ namespace WixToolset.Core.Burn
334 return; 334 return;
335 } 335 }
336 336
337 IEnumerable<PackageFacade> orderedFacades;
338 IEnumerable<WixBundleRollbackBoundarySymbol> boundaries; 337 IEnumerable<WixBundleRollbackBoundarySymbol> boundaries;
339 { 338 {
340 var command = new OrderPackagesAndRollbackBoundariesCommand(this.Messaging, section, facades); 339 var command = new OrderPackagesAndRollbackBoundariesCommand(this.Messaging, section, facades);
341 command.Execute(); 340 command.Execute();
342 341
343 orderedFacades = command.OrderedPackageFacades;
344 boundaries = command.UsedRollbackBoundaries; 342 boundaries = command.UsedRollbackBoundaries;
345 } 343 }
346 344
@@ -351,7 +349,7 @@ namespace WixToolset.Core.Burn
351 } 349 }
352 350
353 { 351 {
354 var command = new ProcessDependencyProvidersCommand(this.Messaging, section, facades); 352 var command = new ProcessDependencyProvidersCommand(this.ServiceProvider, section, facades);
355 command.Execute(); 353 command.Execute();
356 354
357 if (!String.IsNullOrEmpty(command.BundleProviderKey)) 355 if (!String.IsNullOrEmpty(command.BundleProviderKey))
@@ -361,7 +359,7 @@ namespace WixToolset.Core.Burn
361 } 359 }
362 360
363 // Update the bundle per-machine/per-user scope based on the chained packages. 361 // Update the bundle per-machine/per-user scope based on the chained packages.
364 this.ResolveBundleInstallScope(section, bundleSymbol, orderedFacades); 362 this.ResolveBundleInstallScope(section, bundleSymbol, facades.OrderedValues);
365 363
366 var softwareTags = section.Symbols.OfType<WixBundleTagSymbol>().ToList(); 364 var softwareTags = section.Symbols.OfType<WixBundleTagSymbol>().ToList();
367 if (softwareTags.Any()) 365 if (softwareTags.Any())
@@ -370,7 +368,7 @@ namespace WixToolset.Core.Burn
370 command.Execute(); 368 command.Execute();
371 } 369 }
372 370
373 this.DetectDuplicateCacheIds(facades); 371 this.DetectDuplicateCacheIds(facades.Values);
374 372
375 if (this.Messaging.EncounteredError) 373 if (this.Messaging.EncounteredError)
376 { 374 {
@@ -413,7 +411,7 @@ namespace WixToolset.Core.Burn
413 // Generate the core-defined BA manifest tables... 411 // Generate the core-defined BA manifest tables...
414 string baManifestPath; 412 string baManifestPath;
415 { 413 {
416 var command = new CreateBootstrapperApplicationManifestCommand(section, bundleSymbol, boundaries, orderedFacades, uxPayloadIndex, payloadSymbols, packagesPayloads, this.IntermediateFolder, this.InternalBurnBackendHelper); 414 var command = new CreateBootstrapperApplicationManifestCommand(section, bundleSymbol, boundaries, facades, uxPayloadIndex, payloadSymbols, packagesPayloads, this.IntermediateFolder, this.InternalBurnBackendHelper);
417 command.Execute(); 415 command.Execute();
418 416
419 var baManifestPayload = command.BootstrapperApplicationManifestPayloadRow; 417 var baManifestPayload = command.BootstrapperApplicationManifestPayloadRow;
@@ -480,7 +478,7 @@ namespace WixToolset.Core.Burn
480 { 478 {
481 var executableName = Path.GetFileName(this.OutputPath); 479 var executableName = Path.GetFileName(this.OutputPath);
482 480
483 var command = new CreateBurnManifestCommand(executableName, section, bundleSymbol, containers.Values, chainSymbol, orderedFacades, boundaries, uxPayloads, payloadSymbols, packagesPayloads, orderedSearches, this.IntermediateFolder); 481 var command = new CreateBurnManifestCommand(executableName, section, bundleSymbol, containers.Values, chainSymbol, facades, boundaries, uxPayloads, payloadSymbols, packagesPayloads, orderedSearches, this.IntermediateFolder);
484 command.Execute(); 482 command.Execute();
485 483
486 manifestPath = command.OutputPath; 484 manifestPath = command.OutputPath;
@@ -637,11 +635,11 @@ namespace WixToolset.Core.Burn
637 } 635 }
638 } 636 }
639 637
640 private void DetectDuplicateCacheIds(IDictionary<string, PackageFacade> facades) 638 private void DetectDuplicateCacheIds(IEnumerable<PackageFacade> facades)
641 { 639 {
642 var duplicateCacheIdDetector = new Dictionary<string, WixBundlePackageSymbol>(); 640 var duplicateCacheIdDetector = new Dictionary<string, WixBundlePackageSymbol>();
643 641
644 foreach (var facade in facades.Values) 642 foreach (var facade in facades)
645 { 643 {
646 if (duplicateCacheIdDetector.TryGetValue(facade.PackageSymbol.CacheId, out var collisionPackage)) 644 if (duplicateCacheIdDetector.TryGetValue(facade.PackageSymbol.CacheId, out var collisionPackage))
647 { 645 {
diff --git a/src/wix/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs b/src/wix/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs
index 610bdd75..740a6e26 100644
--- a/src/wix/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs
@@ -71,6 +71,7 @@ namespace WixToolset.Core.Burn.Bind
71 case SymbolDefinitionType.WixBundleExePackagePayload: 71 case SymbolDefinitionType.WixBundleExePackagePayload:
72 case SymbolDefinitionType.WixBundleExtension: 72 case SymbolDefinitionType.WixBundleExtension:
73 case SymbolDefinitionType.WixBundleHarvestedBundlePackage: 73 case SymbolDefinitionType.WixBundleHarvestedBundlePackage:
74 case SymbolDefinitionType.WixBundleHarvestedDependencyProvider:
74 case SymbolDefinitionType.WixBundleHarvestedMsiPackage: 75 case SymbolDefinitionType.WixBundleHarvestedMsiPackage:
75 case SymbolDefinitionType.WixBundleHarvestedMspPackage: 76 case SymbolDefinitionType.WixBundleHarvestedMspPackage:
76 case SymbolDefinitionType.WixBundleMsiFeature: 77 case SymbolDefinitionType.WixBundleMsiFeature:
diff --git a/src/wix/WixToolset.Core.Burn/Bind/ProcessDependencyProvidersCommand.cs b/src/wix/WixToolset.Core.Burn/Bind/ProcessDependencyProvidersCommand.cs
index e4e04845..992ce3d6 100644
--- a/src/wix/WixToolset.Core.Burn/Bind/ProcessDependencyProvidersCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bind/ProcessDependencyProvidersCommand.cs
@@ -12,11 +12,12 @@ namespace WixToolset.Core.Burn.Bind
12 12
13 internal class ProcessDependencyProvidersCommand 13 internal class ProcessDependencyProvidersCommand
14 { 14 {
15 public ProcessDependencyProvidersCommand(IMessaging messaging, IntermediateSection section, IDictionary<string, PackageFacade> facades) 15 public ProcessDependencyProvidersCommand(IServiceProvider serviceProvider, IntermediateSection section, PackageFacades facades)
16 { 16 {
17 this.Messaging = messaging; 17 this.Messaging = serviceProvider.GetService<IMessaging>();
18 this.Section = section; 18 this.BackendHelper = serviceProvider.GetService<IBackendHelper>();
19 19
20 this.Section = section;
20 this.Facades = facades; 21 this.Facades = facades;
21 } 22 }
22 23
@@ -24,9 +25,11 @@ namespace WixToolset.Core.Burn.Bind
24 25
25 private IMessaging Messaging { get; } 26 private IMessaging Messaging { get; }
26 27
28 private IBackendHelper BackendHelper { get; }
29
27 private IntermediateSection Section { get; } 30 private IntermediateSection Section { get; }
28 31
29 private IDictionary<string, PackageFacade> Facades { get; } 32 private PackageFacades Facades { get; }
30 33
31 /// <summary> 34 /// <summary>
32 /// Sets the explicitly provided bundle provider key, if provided. And... 35 /// Sets the explicitly provided bundle provider key, if provided. And...
@@ -36,23 +39,29 @@ namespace WixToolset.Core.Burn.Bind
36 /// </summary> 39 /// </summary>
37 public void Execute() 40 public void Execute()
38 { 41 {
42 this.ProcessHarvestedProviders();
43
39 var dependencySymbols = this.Section.Symbols.OfType<WixDependencyProviderSymbol>(); 44 var dependencySymbols = this.Section.Symbols.OfType<WixDependencyProviderSymbol>();
40 45
41 foreach (var dependency in dependencySymbols) 46 foreach (var dependency in dependencySymbols)
42 { 47 {
43 // Sets the provider key for the bundle, if it is not set already. 48 // Sets the provider key for the bundle, if it is not set already.
44 if (String.IsNullOrEmpty(this.BundleProviderKey)) 49 if (dependency.Bundle)
45 { 50 {
46 if (dependency.Bundle) 51 if (String.IsNullOrEmpty(this.BundleProviderKey))
47 { 52 {
48 this.BundleProviderKey = dependency.ProviderKey; 53 this.BundleProviderKey = dependency.ProviderKey;
49 } 54 }
55 else
56 {
57 this.Messaging.Write(BurnBackendErrors.BundleMultipleProviders(dependency.SourceLineNumbers, dependency.ProviderKey, this.BundleProviderKey));
58 }
50 } 59 }
51 60
52 // Import any authored dependencies. These may merge with imported provides from MSI packages. 61 // Import any authored dependencies. These may merge with imported provides from MSI packages.
53 var packageId = dependency.ParentRef; 62 var packageId = dependency.ParentRef;
54 63
55 if (this.Facades.TryGetValue(packageId, out var facade)) 64 if (this.Facades.TryGetFacadeByPackageId(packageId, out var facade))
56 { 65 {
57 if (String.IsNullOrEmpty(dependency.ProviderKey)) 66 if (String.IsNullOrEmpty(dependency.ProviderKey))
58 { 67 {
@@ -142,5 +151,31 @@ namespace WixToolset.Core.Burn.Bind
142 151
143 return dependencySymbolsByPackageId; 152 return dependencySymbolsByPackageId;
144 } 153 }
154
155 private void ProcessHarvestedProviders()
156 {
157 var harvestedDependencies = this.Section.Symbols.OfType<WixBundleHarvestedDependencyProviderSymbol>().ToList();
158 foreach (var harvestedDependency in harvestedDependencies)
159 {
160 if (!this.Facades.TryGetFacadesByPackagePayloadId(harvestedDependency.PackagePayloadRef, out var facades))
161 {
162 this.Messaging.Write(ErrorMessages.IdentifierNotFound("Package.PayloadRef", harvestedDependency.PackagePayloadRef));
163 continue;
164 }
165
166 foreach (var facade in facades)
167 {
168 var depId = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", facade.PackageId, harvestedDependency.Id.Id));
169 this.Section.AddSymbol(new WixDependencyProviderSymbol(harvestedDependency.SourceLineNumbers, depId)
170 {
171 ParentRef = facade.PackageId,
172 ProviderKey = harvestedDependency.ProviderKey,
173 Version = harvestedDependency.Version,
174 DisplayName = harvestedDependency.DisplayName,
175 Attributes = WixDependencyProviderAttributes.ProvidesAttributesImported | (WixDependencyProviderAttributes)harvestedDependency.ProviderAttributes,
176 });
177 }
178 }
179 }
145 } 180 }
146} 181}
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/AutomaticallySlipstreamPatchesCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/AutomaticallySlipstreamPatchesCommand.cs
index 064bc62a..0c1b4fcb 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/AutomaticallySlipstreamPatchesCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/AutomaticallySlipstreamPatchesCommand.cs
@@ -7,18 +7,22 @@ namespace WixToolset.Core.Burn.Bundles
7 using System.Linq; 7 using System.Linq;
8 using WixToolset.Data; 8 using WixToolset.Data;
9 using WixToolset.Data.Symbols; 9 using WixToolset.Data.Symbols;
10 using WixToolset.Extensibility.Services;
10 11
11 internal class AutomaticallySlipstreamPatchesCommand 12 internal class AutomaticallySlipstreamPatchesCommand
12 { 13 {
13 public AutomaticallySlipstreamPatchesCommand(IntermediateSection section, ICollection<PackageFacade> packageFacades) 14 public AutomaticallySlipstreamPatchesCommand(IMessaging messaging, IntermediateSection section, PackageFacades packageFacades)
14 { 15 {
16 this.Messaging = messaging;
15 this.Section = section; 17 this.Section = section;
16 this.PackageFacades = packageFacades; 18 this.PackageFacades = packageFacades;
17 } 19 }
18 20
21 private IMessaging Messaging { get; }
22
19 private IntermediateSection Section { get; } 23 private IntermediateSection Section { get; }
20 24
21 private IEnumerable<PackageFacade> PackageFacades { get; } 25 private PackageFacades PackageFacades { get; }
22 26
23 public void Execute() 27 public void Execute()
24 { 28 {
@@ -26,7 +30,7 @@ namespace WixToolset.Core.Burn.Bundles
26 var targetsProductCode = new Dictionary<string, List<WixBundlePatchTargetCodeSymbol>>(); 30 var targetsProductCode = new Dictionary<string, List<WixBundlePatchTargetCodeSymbol>>();
27 var targetsUpgradeCode = new Dictionary<string, List<WixBundlePatchTargetCodeSymbol>>(); 31 var targetsUpgradeCode = new Dictionary<string, List<WixBundlePatchTargetCodeSymbol>>();
28 32
29 foreach (var facade in this.PackageFacades) 33 foreach (var facade in this.PackageFacades.Values)
30 { 34 {
31 // Keep track of all MSI packages. 35 // Keep track of all MSI packages.
32 if (facade.SpecificPackageSymbol is WixBundleMsiPackageSymbol msiPackage) 36 if (facade.SpecificPackageSymbol is WixBundleMsiPackageSymbol msiPackage)
@@ -37,7 +41,7 @@ namespace WixToolset.Core.Burn.Bundles
37 { 41 {
38 var patchTargetCodeSymbols = this.Section.Symbols 42 var patchTargetCodeSymbols = this.Section.Symbols
39 .OfType<WixBundlePatchTargetCodeSymbol>() 43 .OfType<WixBundlePatchTargetCodeSymbol>()
40 .Where(r => r.PackageRef == facade.PackageId); 44 .Where(r => r.PackagePayloadRef == facade.PackageSymbol.PayloadRef);
41 45
42 // Index target ProductCodes and UpgradeCodes for slipstreamed MSPs. 46 // Index target ProductCodes and UpgradeCodes for slipstreamed MSPs.
43 foreach (var symbol in patchTargetCodeSymbols) 47 foreach (var symbol in patchTargetCodeSymbols)
@@ -89,22 +93,27 @@ namespace WixToolset.Core.Burn.Bundles
89 } 93 }
90 } 94 }
91 95
92 private bool TryAddSlipstreamSymbol(HashSet<string> slipstreamMspIds, WixBundleMsiPackageSymbol msiPackage, WixBundlePatchTargetCodeSymbol patchTargetCode) 96 private void TryAddSlipstreamSymbol(HashSet<string> slipstreamMspIds, WixBundleMsiPackageSymbol msiPackage, WixBundlePatchTargetCodeSymbol patchTargetCode)
93 { 97 {
94 var id = new Identifier(AccessModifier.Section, msiPackage.Id.Id, patchTargetCode.PackageRef); 98 if (!this.PackageFacades.TryGetFacadesByPackagePayloadId(patchTargetCode.PackagePayloadRef, out var packageFacades))
99 {
100 this.Messaging.Write(ErrorMessages.IdentifierNotFound("Package.PayloadRef", patchTargetCode.PackagePayloadRef));
101 return;
102 }
95 103
96 if (slipstreamMspIds.Add(id.Id)) 104 foreach (var packageFacade in packageFacades)
97 { 105 {
98 this.Section.AddSymbol(new WixBundleSlipstreamMspSymbol(patchTargetCode.SourceLineNumbers) 106 var id = new Identifier(AccessModifier.Section, msiPackage.Id.Id, packageFacade.PackageId);
99 {
100 TargetPackageRef = msiPackage.Id.Id,
101 MspPackageRef = patchTargetCode.PackageRef,
102 });
103 107
104 return true; 108 if (slipstreamMspIds.Add(id.Id))
109 {
110 this.Section.AddSymbol(new WixBundleSlipstreamMspSymbol(patchTargetCode.SourceLineNumbers)
111 {
112 TargetPackageRef = msiPackage.Id.Id,
113 MspPackageRef = packageFacade.PackageId,
114 });
115 }
105 } 116 }
106
107 return false;
108 } 117 }
109 } 118 }
110} 119}
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/CreateBootstrapperApplicationManifestCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/CreateBootstrapperApplicationManifestCommand.cs
index b993da87..39347d19 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/CreateBootstrapperApplicationManifestCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/CreateBootstrapperApplicationManifestCommand.cs
@@ -15,12 +15,12 @@ namespace WixToolset.Core.Burn.Bundles
15 15
16 internal class CreateBootstrapperApplicationManifestCommand 16 internal class CreateBootstrapperApplicationManifestCommand
17 { 17 {
18 public CreateBootstrapperApplicationManifestCommand(IntermediateSection section, WixBundleSymbol bundleSymbol, IEnumerable<WixBundleRollbackBoundarySymbol> boundaries, IEnumerable<PackageFacade> chainPackages, int lastUXPayloadIndex, Dictionary<string, WixBundlePayloadSymbol> payloadSymbols, Dictionary<string, Dictionary<string, WixBundlePayloadSymbol>> packagesPayloads, string intermediateFolder, IInternalBurnBackendHelper internalBurnBackendHelper) 18 public CreateBootstrapperApplicationManifestCommand(IntermediateSection section, WixBundleSymbol bundleSymbol, IEnumerable<WixBundleRollbackBoundarySymbol> boundaries, PackageFacades packageFacades, int lastUXPayloadIndex, Dictionary<string, WixBundlePayloadSymbol> payloadSymbols, Dictionary<string, Dictionary<string, WixBundlePayloadSymbol>> packagesPayloads, string intermediateFolder, IInternalBurnBackendHelper internalBurnBackendHelper)
19 { 19 {
20 this.Section = section; 20 this.Section = section;
21 this.BundleSymbol = bundleSymbol; 21 this.BundleSymbol = bundleSymbol;
22 this.RollbackBoundaries = boundaries; 22 this.RollbackBoundaries = boundaries;
23 this.ChainPackages = chainPackages; 23 this.PackagesFacades = packageFacades;
24 this.LastUXPayloadIndex = lastUXPayloadIndex; 24 this.LastUXPayloadIndex = lastUXPayloadIndex;
25 this.Payloads = payloadSymbols; 25 this.Payloads = payloadSymbols;
26 this.PackagesPayloads = packagesPayloads; 26 this.PackagesPayloads = packagesPayloads;
@@ -34,7 +34,7 @@ namespace WixToolset.Core.Burn.Bundles
34 34
35 private IEnumerable<WixBundleRollbackBoundarySymbol> RollbackBoundaries { get; } 35 private IEnumerable<WixBundleRollbackBoundarySymbol> RollbackBoundaries { get; }
36 36
37 private IEnumerable<PackageFacade> ChainPackages { get; } 37 private PackageFacades PackagesFacades { get; }
38 38
39 private IInternalBurnBackendHelper InternalBurnBackendHelper { get; } 39 private IInternalBurnBackendHelper InternalBurnBackendHelper { get; }
40 40
@@ -141,7 +141,7 @@ namespace WixToolset.Core.Burn.Bundles
141 141
142 private void WritePackageInfo(XmlTextWriter writer) 142 private void WritePackageInfo(XmlTextWriter writer)
143 { 143 {
144 foreach (var package in this.ChainPackages) 144 foreach (var package in this.PackagesFacades.OrderedValues)
145 { 145 {
146 if (!this.PackagesPayloads.TryGetValue(package.PackageId, out var payloads)) 146 if (!this.PackagesPayloads.TryGetValue(package.PackageId, out var payloads))
147 { 147 {
@@ -229,33 +229,46 @@ namespace WixToolset.Core.Burn.Bundles
229 229
230 foreach (var featureSymbol in featureSymbols) 230 foreach (var featureSymbol in featureSymbols)
231 { 231 {
232 writer.WriteStartElement("WixPackageFeatureInfo"); 232 if (!this.PackagesFacades.TryGetFacadesByPackagePayloadId(featureSymbol.PackagePayloadRef, out var facades))
233
234 writer.WriteAttributeString("Package", featureSymbol.PackageRef);
235 writer.WriteAttributeString("Feature", featureSymbol.Name);
236 writer.WriteAttributeString("Size", featureSymbol.Size.ToString(CultureInfo.InvariantCulture));
237
238 if (!String.IsNullOrEmpty(featureSymbol.Parent))
239 { 233 {
240 writer.WriteAttributeString("Parent", featureSymbol.Parent); 234 continue;
241 } 235 }
242 236
243 if (!String.IsNullOrEmpty(featureSymbol.Title)) 237 foreach (var facade in facades)
244 { 238 {
245 writer.WriteAttributeString("Title", featureSymbol.Title); 239 if (!(facade.SpecificPackageSymbol is WixBundleMsiPackageSymbol msiPackage) || !msiPackage.EnableFeatureSelection)
246 } 240 {
241 continue;
242 }
247 243
248 if (!String.IsNullOrEmpty(featureSymbol.Description)) 244 writer.WriteStartElement("WixPackageFeatureInfo");
249 {
250 writer.WriteAttributeString("Description", featureSymbol.Description);
251 }
252 245
253 writer.WriteAttributeString("Display", featureSymbol.Display.ToString(CultureInfo.InvariantCulture)); 246 writer.WriteAttributeString("Package", facade.PackageId);
254 writer.WriteAttributeString("Level", featureSymbol.Level.ToString(CultureInfo.InvariantCulture)); 247 writer.WriteAttributeString("Feature", featureSymbol.Name);
255 writer.WriteAttributeString("Directory", featureSymbol.Directory); 248 writer.WriteAttributeString("Size", featureSymbol.Size.ToString(CultureInfo.InvariantCulture));
256 writer.WriteAttributeString("Attributes", featureSymbol.Attributes.ToString(CultureInfo.InvariantCulture));
257 249
258 writer.WriteEndElement(); 250 if (!String.IsNullOrEmpty(featureSymbol.Parent))
251 {
252 writer.WriteAttributeString("Parent", featureSymbol.Parent);
253 }
254
255 if (!String.IsNullOrEmpty(featureSymbol.Title))
256 {
257 writer.WriteAttributeString("Title", featureSymbol.Title);
258 }
259
260 if (!String.IsNullOrEmpty(featureSymbol.Description))
261 {
262 writer.WriteAttributeString("Description", featureSymbol.Description);
263 }
264
265 writer.WriteAttributeString("Display", featureSymbol.Display.ToString(CultureInfo.InvariantCulture));
266 writer.WriteAttributeString("Level", featureSymbol.Level.ToString(CultureInfo.InvariantCulture));
267 writer.WriteAttributeString("Directory", featureSymbol.Directory);
268 writer.WriteAttributeString("Attributes", featureSymbol.Attributes.ToString(CultureInfo.InvariantCulture));
269
270 writer.WriteEndElement();
271 }
259 } 272 }
260 } 273 }
261 274
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
index be5fdf0d..508395f5 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
@@ -18,14 +18,14 @@ namespace WixToolset.Core.Burn.Bundles
18 18
19 internal class CreateBurnManifestCommand 19 internal class CreateBurnManifestCommand
20 { 20 {
21 public CreateBurnManifestCommand(string executableName, IntermediateSection section, WixBundleSymbol bundleSymbol, IEnumerable<WixBundleContainerSymbol> containers, WixChainSymbol chainSymbol, IEnumerable<PackageFacade> orderedPackages, IEnumerable<WixBundleRollbackBoundarySymbol> boundaries, IEnumerable<WixBundlePayloadSymbol> uxPayloads, Dictionary<string, WixBundlePayloadSymbol> allPayloadsById, Dictionary<string, Dictionary<string, WixBundlePayloadSymbol>> packagesPayloads, IEnumerable<ISearchFacade> orderedSearches, string intermediateFolder) 21 public CreateBurnManifestCommand(string executableName, IntermediateSection section, WixBundleSymbol bundleSymbol, IEnumerable<WixBundleContainerSymbol> containers, WixChainSymbol chainSymbol, PackageFacades packageFacades, IEnumerable<WixBundleRollbackBoundarySymbol> boundaries, IEnumerable<WixBundlePayloadSymbol> uxPayloads, Dictionary<string, WixBundlePayloadSymbol> allPayloadsById, Dictionary<string, Dictionary<string, WixBundlePayloadSymbol>> packagesPayloads, IEnumerable<ISearchFacade> orderedSearches, string intermediateFolder)
22 { 22 {
23 this.ExecutableName = executableName; 23 this.ExecutableName = executableName;
24 this.Section = section; 24 this.Section = section;
25 this.BundleSymbol = bundleSymbol; 25 this.BundleSymbol = bundleSymbol;
26 this.Chain = chainSymbol; 26 this.Chain = chainSymbol;
27 this.Containers = containers; 27 this.Containers = containers;
28 this.OrderedPackages = orderedPackages; 28 this.PackageFacades = packageFacades;
29 this.RollbackBoundaries = boundaries; 29 this.RollbackBoundaries = boundaries;
30 this.UXContainerPayloads = uxPayloads; 30 this.UXContainerPayloads = uxPayloads;
31 this.Payloads = allPayloadsById; 31 this.Payloads = allPayloadsById;
@@ -46,7 +46,7 @@ namespace WixToolset.Core.Burn.Bundles
46 46
47 private IEnumerable<WixBundleRollbackBoundarySymbol> RollbackBoundaries { get; } 47 private IEnumerable<WixBundleRollbackBoundarySymbol> RollbackBoundaries { get; }
48 48
49 private IEnumerable<PackageFacade> OrderedPackages { get; } 49 private PackageFacades PackageFacades { get; }
50 50
51 private IEnumerable<ISearchFacade> OrderedSearches { get; } 51 private IEnumerable<ISearchFacade> OrderedSearches { get; }
52 52
@@ -316,11 +316,11 @@ namespace WixToolset.Core.Burn.Bundles
316 } 316 }
317 317
318 // Index a few tables by package. 318 // Index a few tables by package.
319 var targetCodesByPatch = this.Section.Symbols.OfType<WixBundlePatchTargetCodeSymbol>().ToLookup(r => r.PackageRef); 319 var targetCodesByPackagePayload = this.Section.Symbols.OfType<WixBundlePatchTargetCodeSymbol>().ToLookup(r => r.PackagePayloadRef);
320 var msiFeaturesByPackage = this.Section.Symbols.OfType<WixBundleMsiFeatureSymbol>().ToLookup(r => r.PackageRef); 320 var msiFeaturesByPackagePayload = this.Section.Symbols.OfType<WixBundleMsiFeatureSymbol>().ToLookup(r => r.PackagePayloadRef);
321 var msiPropertiesByPackage = this.Section.Symbols.OfType<WixBundleMsiPropertySymbol>().ToLookup(r => r.PackageRef); 321 var msiPropertiesByPackage = this.Section.Symbols.OfType<WixBundleMsiPropertySymbol>().ToLookup(r => r.PackageRef);
322 var relatedBundlesByPackage = this.Section.Symbols.OfType<WixBundlePackageRelatedBundleSymbol>().ToLookup(r => r.PackageRef); 322 var relatedBundlesByPackagePayload = this.Section.Symbols.OfType<WixBundlePackageRelatedBundleSymbol>().ToLookup(r => r.PackagePayloadRef);
323 var relatedPackagesByPackage = this.Section.Symbols.OfType<WixBundleRelatedPackageSymbol>().ToLookup(r => r.PackageRef); 323 var relatedPackagesByPackagePayload = this.Section.Symbols.OfType<WixBundleRelatedPackageSymbol>().ToLookup(r => r.PackagePayloadRef);
324 var slipstreamMspsByPackage = this.Section.Symbols.OfType<WixBundleSlipstreamMspSymbol>().ToLookup(r => r.TargetPackageRef); 324 var slipstreamMspsByPackage = this.Section.Symbols.OfType<WixBundleSlipstreamMspSymbol>().ToLookup(r => r.TargetPackageRef);
325 var exitCodesByPackage = this.Section.Symbols.OfType<WixBundlePackageExitCodeSymbol>().ToLookup(r => r.ChainPackageId); 325 var exitCodesByPackage = this.Section.Symbols.OfType<WixBundlePackageExitCodeSymbol>().ToLookup(r => r.ChainPackageId);
326 var commandLinesByPackage = this.Section.Symbols.OfType<WixBundlePackageCommandLineSymbol>().ToLookup(r => r.WixBundlePackageRef); 326 var commandLinesByPackage = this.Section.Symbols.OfType<WixBundlePackageCommandLineSymbol>().ToLookup(r => r.WixBundlePackageRef);
@@ -331,8 +331,10 @@ namespace WixToolset.Core.Burn.Bundles
331 // Build up the list of target codes from all the MSPs in the chain. 331 // Build up the list of target codes from all the MSPs in the chain.
332 var targetCodes = new List<WixBundlePatchTargetCodeSymbol>(); 332 var targetCodes = new List<WixBundlePatchTargetCodeSymbol>();
333 333
334 foreach (var package in this.OrderedPackages) 334 foreach (var package in this.PackageFacades.OrderedValues)
335 { 335 {
336 var packagePayloadId = package.PackageSymbol.PayloadRef;
337
336 writer.WriteStartElement(String.Format(CultureInfo.InvariantCulture, "{0}Package", package.PackageSymbol.Type)); 338 writer.WriteStartElement(String.Format(CultureInfo.InvariantCulture, "{0}Package", package.PackageSymbol.Type));
337 339
338 writer.WriteAttributeString("Id", package.PackageId); 340 writer.WriteAttributeString("Id", package.PackageId);
@@ -425,6 +427,19 @@ namespace WixToolset.Core.Burn.Bundles
425 { 427 {
426 writer.WriteAttributeString("UpgradeCode", msiPackage.UpgradeCode); 428 writer.WriteAttributeString("UpgradeCode", msiPackage.UpgradeCode);
427 } 429 }
430
431 // If feature selection is enabled, represent the Feature table in the manifest.
432 if (msiPackage.EnableFeatureSelection)
433 {
434 var packageMsiFeatures = msiFeaturesByPackagePayload[packagePayloadId];
435
436 foreach (var feature in packageMsiFeatures)
437 {
438 writer.WriteStartElement("MsiFeature");
439 writer.WriteAttributeString("Id", feature.Name);
440 writer.WriteEndElement();
441 }
442 }
428 } 443 }
429 else if (package.SpecificPackageSymbol is WixBundleMspPackageSymbol mspPackage) // MSP 444 else if (package.SpecificPackageSymbol is WixBundleMspPackageSymbol mspPackage) // MSP
430 { 445 {
@@ -435,7 +450,7 @@ namespace WixToolset.Core.Burn.Bundles
435 // product codes, add the patch list to the overall list. 450 // product codes, add the patch list to the overall list.
436 if (null != targetCodes) 451 if (null != targetCodes)
437 { 452 {
438 foreach (var patchTargetCode in targetCodesByPatch[mspPackage.Id.Id]) 453 foreach (var patchTargetCode in targetCodesByPackagePayload[packagePayloadId])
439 { 454 {
440 if (patchTargetCode.Type == WixBundlePatchTargetCodeType.Unspecified) 455 if (patchTargetCode.Type == WixBundlePatchTargetCodeType.Unspecified)
441 { 456 {
@@ -453,15 +468,6 @@ namespace WixToolset.Core.Burn.Bundles
453 writer.WriteAttributeString("KB", msuPackage.MsuKB); 468 writer.WriteAttributeString("KB", msuPackage.MsuKB);
454 } 469 }
455 470
456 var packageMsiFeatures = msiFeaturesByPackage[package.PackageId];
457
458 foreach (var feature in packageMsiFeatures)
459 {
460 writer.WriteStartElement("MsiFeature");
461 writer.WriteAttributeString("Id", feature.Name);
462 writer.WriteEndElement();
463 }
464
465 var packageMsiProperties = msiPropertiesByPackage[package.PackageId]; 471 var packageMsiProperties = msiPropertiesByPackage[package.PackageId];
466 472
467 foreach (var msiProperty in packageMsiProperties) 473 foreach (var msiProperty in packageMsiProperties)
@@ -536,14 +542,14 @@ namespace WixToolset.Core.Burn.Bundles
536 542
537 if (dependency.Imported) 543 if (dependency.Imported)
538 { 544 {
539 // The package dependency was explicitly authored into the manifest. 545 // The package dependency was harvested from the package.
540 writer.WriteAttributeString("Imported", "yes"); 546 writer.WriteAttributeString("Imported", "yes");
541 } 547 }
542 548
543 writer.WriteEndElement(); 549 writer.WriteEndElement();
544 } 550 }
545 551
546 var packageRelatedBundles = relatedBundlesByPackage[package.PackageId]; 552 var packageRelatedBundles = relatedBundlesByPackagePayload[packagePayloadId];
547 553
548 foreach (var relatedBundle in packageRelatedBundles) 554 foreach (var relatedBundle in packageRelatedBundles)
549 { 555 {
@@ -553,7 +559,7 @@ namespace WixToolset.Core.Burn.Bundles
553 writer.WriteEndElement(); 559 writer.WriteEndElement();
554 } 560 }
555 561
556 var packageRelatedPackages = relatedPackagesByPackage[package.PackageId]; 562 var packageRelatedPackages = relatedPackagesByPackagePayload[packagePayloadId];
557 563
558 foreach (var related in packageRelatedPackages) 564 foreach (var related in packageRelatedPackages)
559 { 565 {
@@ -587,7 +593,6 @@ namespace WixToolset.Core.Burn.Bundles
587 } 593 }
588 594
589 // Write any contained Payloads with the PackagePayload being first 595 // Write any contained Payloads with the PackagePayload being first
590 var packagePayloadId = package.PackageSymbol.PayloadRef;
591 writer.WriteStartElement("PayloadRef"); 596 writer.WriteStartElement("PayloadRef");
592 writer.WriteAttributeString("Id", packagePayloadId); 597 writer.WriteAttributeString("Id", packagePayloadId);
593 writer.WriteEndElement(); 598 writer.WriteEndElement();
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/GetPackageFacadesCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/GetPackageFacadesCommand.cs
index 19403631..f8c70c1a 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/GetPackageFacadesCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/GetPackageFacadesCommand.cs
@@ -23,7 +23,7 @@ namespace WixToolset.Core.Burn.Bundles
23 23
24 private IntermediateSection Section { get; } 24 private IntermediateSection Section { get; }
25 25
26 public IDictionary<string, PackageFacade> PackageFacades { get; private set; } 26 public PackageFacades PackageFacades { get; private set; }
27 27
28 public void Execute() 28 public void Execute()
29 { 29 {
@@ -39,7 +39,7 @@ namespace WixToolset.Core.Burn.Bundles
39 var mspPackagePayloads = this.Section.Symbols.OfType<WixBundleMspPackagePayloadSymbol>().ToDictionary(t => t.Id.Id); 39 var mspPackagePayloads = this.Section.Symbols.OfType<WixBundleMspPackagePayloadSymbol>().ToDictionary(t => t.Id.Id);
40 var msuPackagePayloads = this.Section.Symbols.OfType<WixBundleMsuPackagePayloadSymbol>().ToDictionary(t => t.Id.Id); 40 var msuPackagePayloads = this.Section.Symbols.OfType<WixBundleMsuPackagePayloadSymbol>().ToDictionary(t => t.Id.Id);
41 41
42 var facades = new Dictionary<string, PackageFacade>(); 42 var facades = new PackageFacades();
43 43
44 foreach (var package in this.ChainPackageSymbols) 44 foreach (var package in this.ChainPackageSymbols)
45 { 45 {
@@ -135,6 +135,7 @@ namespace WixToolset.Core.Burn.Bundles
135 if (packagePayload == null) 135 if (packagePayload == null)
136 { 136 {
137 this.Messaging.Write(ErrorMessages.MissingPackagePayload(package.SourceLineNumbers, id, package.Type.ToString())); 137 this.Messaging.Write(ErrorMessages.MissingPackagePayload(package.SourceLineNumbers, id, package.Type.ToString()));
138 continue;
138 } 139 }
139 else 140 else
140 { 141 {
@@ -146,7 +147,7 @@ namespace WixToolset.Core.Burn.Bundles
146 case WixBundlePackageType.Bundle: 147 case WixBundlePackageType.Bundle:
147 if (bundlePackages.TryGetValue(id, out var bundlePackage)) 148 if (bundlePackages.TryGetValue(id, out var bundlePackage))
148 { 149 {
149 facades.Add(id, new PackageFacade(package, bundlePackage)); 150 facades.Add(new PackageFacade(package, bundlePackage));
150 } 151 }
151 else 152 else
152 { 153 {
@@ -157,7 +158,7 @@ namespace WixToolset.Core.Burn.Bundles
157 case WixBundlePackageType.Exe: 158 case WixBundlePackageType.Exe:
158 if (exePackages.TryGetValue(id, out var exePackage)) 159 if (exePackages.TryGetValue(id, out var exePackage))
159 { 160 {
160 facades.Add(id, new PackageFacade(package, exePackage)); 161 facades.Add(new PackageFacade(package, exePackage));
161 } 162 }
162 else 163 else
163 { 164 {
@@ -168,7 +169,7 @@ namespace WixToolset.Core.Burn.Bundles
168 case WixBundlePackageType.Msi: 169 case WixBundlePackageType.Msi:
169 if (msiPackages.TryGetValue(id, out var msiPackage)) 170 if (msiPackages.TryGetValue(id, out var msiPackage))
170 { 171 {
171 facades.Add(id, new PackageFacade(package, msiPackage)); 172 facades.Add(new PackageFacade(package, msiPackage));
172 } 173 }
173 else 174 else
174 { 175 {
@@ -179,7 +180,7 @@ namespace WixToolset.Core.Burn.Bundles
179 case WixBundlePackageType.Msp: 180 case WixBundlePackageType.Msp:
180 if (mspPackages.TryGetValue(id, out var mspPackage)) 181 if (mspPackages.TryGetValue(id, out var mspPackage))
181 { 182 {
182 facades.Add(id, new PackageFacade(package, mspPackage)); 183 facades.Add(new PackageFacade(package, mspPackage));
183 } 184 }
184 else 185 else
185 { 186 {
@@ -190,7 +191,7 @@ namespace WixToolset.Core.Burn.Bundles
190 case WixBundlePackageType.Msu: 191 case WixBundlePackageType.Msu:
191 if (msuPackages.TryGetValue(id, out var msuPackage)) 192 if (msuPackages.TryGetValue(id, out var msuPackage))
192 { 193 {
193 facades.Add(id, new PackageFacade(package, msuPackage)); 194 facades.Add(new PackageFacade(package, msuPackage));
194 } 195 }
195 else 196 else
196 { 197 {
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/OrderPackagesAndRollbackBoundariesCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/OrderPackagesAndRollbackBoundariesCommand.cs
index 99e1e196..13aa60e3 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/OrderPackagesAndRollbackBoundariesCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/OrderPackagesAndRollbackBoundariesCommand.cs
@@ -12,7 +12,7 @@ namespace WixToolset.Core.Burn.Bundles
12 12
13 internal class OrderPackagesAndRollbackBoundariesCommand 13 internal class OrderPackagesAndRollbackBoundariesCommand
14 { 14 {
15 public OrderPackagesAndRollbackBoundariesCommand(IMessaging messaging, IntermediateSection section, IDictionary<string, PackageFacade> packageFacades) 15 public OrderPackagesAndRollbackBoundariesCommand(IMessaging messaging, IntermediateSection section, PackageFacades packageFacades)
16 { 16 {
17 this.Messaging = messaging; 17 this.Messaging = messaging;
18 this.Section = section; 18 this.Section = section;
@@ -23,9 +23,7 @@ namespace WixToolset.Core.Burn.Bundles
23 23
24 private IntermediateSection Section { get; } 24 private IntermediateSection Section { get; }
25 25
26 private IDictionary<string, PackageFacade> PackageFacades { get; } 26 private PackageFacades PackageFacades { get; }
27
28 public IEnumerable<PackageFacade> OrderedPackageFacades { get; private set; }
29 27
30 public IEnumerable<WixBundleRollbackBoundarySymbol> UsedRollbackBoundaries { get; private set; } 28 public IEnumerable<WixBundleRollbackBoundarySymbol> UsedRollbackBoundaries { get; private set; }
31 29
@@ -34,7 +32,6 @@ namespace WixToolset.Core.Burn.Bundles
34 var groupSymbols = this.Section.Symbols.OfType<WixGroupSymbol>().ToList(); 32 var groupSymbols = this.Section.Symbols.OfType<WixGroupSymbol>().ToList();
35 var boundariesById = this.Section.Symbols.OfType<WixBundleRollbackBoundarySymbol>().ToDictionary(b => b.Id.Id); 33 var boundariesById = this.Section.Symbols.OfType<WixBundleRollbackBoundarySymbol>().ToDictionary(b => b.Id.Id);
36 34
37 var orderedFacades = new List<PackageFacade>();
38 var usedBoundaries = new List<WixBundleRollbackBoundarySymbol>(); 35 var usedBoundaries = new List<WixBundleRollbackBoundarySymbol>();
39 36
40 // Process the chain of packages to add them in the correct order 37 // Process the chain of packages to add them in the correct order
@@ -55,7 +52,7 @@ namespace WixToolset.Core.Burn.Bundles
55 { 52 {
56 if (ComplexReferenceChildType.Package == groupSymbol.ChildType && ComplexReferenceParentType.PackageGroup == groupSymbol.ParentType && BurnConstants.BundleChainPackageGroupId == groupSymbol.ParentId) 53 if (ComplexReferenceChildType.Package == groupSymbol.ChildType && ComplexReferenceParentType.PackageGroup == groupSymbol.ParentType && BurnConstants.BundleChainPackageGroupId == groupSymbol.ParentId)
57 { 54 {
58 if (this.PackageFacades.TryGetValue(groupSymbol.ChildId, out var facade)) 55 if (this.PackageFacades.TryGetFacadeByPackageId(groupSymbol.ChildId, out var facade))
59 { 56 {
60 var insideMsiTransaction = lastRollbackBoundary.Transaction; 57 var insideMsiTransaction = lastRollbackBoundary.Transaction;
61 58
@@ -102,7 +99,7 @@ namespace WixToolset.Core.Burn.Bundles
102 } 99 }
103 } 100 }
104 101
105 orderedFacades.Add(facade); 102 this.PackageFacades.AddOrdered(facade);
106 } 103 }
107 else // must be a rollback boundary. 104 else // must be a rollback boundary.
108 { 105 {
@@ -158,7 +155,7 @@ namespace WixToolset.Core.Burn.Bundles
158 string previousRollbackBoundaryId = null; 155 string previousRollbackBoundaryId = null;
159 PackageFacade previousFacade = null; 156 PackageFacade previousFacade = null;
160 157
161 foreach (var package in orderedFacades) 158 foreach (var package in this.PackageFacades.OrderedValues)
162 { 159 {
163 if (null != package.PackageSymbol.RollbackBoundaryRef) 160 if (null != package.PackageSymbol.RollbackBoundaryRef)
164 { 161 {
@@ -178,7 +175,6 @@ namespace WixToolset.Core.Burn.Bundles
178 previousFacade.PackageSymbol.RollbackBoundaryBackwardRef = previousRollbackBoundaryId; 175 previousFacade.PackageSymbol.RollbackBoundaryBackwardRef = previousRollbackBoundaryId;
179 } 176 }
180 177
181 this.OrderedPackageFacades = orderedFacades;
182 this.UsedRollbackBoundaries = usedBoundaries; 178 this.UsedRollbackBoundaries = usedBoundaries;
183 } 179 }
184 } 180 }
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/PackageFacades.cs b/src/wix/WixToolset.Core.Burn/Bundles/PackageFacades.cs
new file mode 100644
index 00000000..a5737505
--- /dev/null
+++ b/src/wix/WixToolset.Core.Burn/Bundles/PackageFacades.cs
@@ -0,0 +1,54 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Core.Burn.Bundles
4{
5 using System.Collections.Generic;
6 using System.Linq;
7 using WixToolset.Data;
8
9 internal class PackageFacades
10 {
11 private Dictionary<string, PackageFacade> FacadesByPackageId { get; } = new Dictionary<string, PackageFacade>();
12
13 private Dictionary<string, List<PackageFacade>> FacadesByPackagePayloadId { get; } = new Dictionary<string, List<PackageFacade>>();
14
15 private List<PackageFacade> OrderedFacades { get; } = new List<PackageFacade>();
16
17 public void Add(PackageFacade item)
18 {
19 this.FacadesByPackageId.Add(item.PackageId, item);
20
21 if (!this.FacadesByPackagePayloadId.TryGetValue(item.PackageSymbol.PayloadRef, out var facades))
22 {
23 facades = new List<PackageFacade>();
24 this.FacadesByPackagePayloadId.Add(item.PackageSymbol.PayloadRef, facades);
25 }
26
27 facades.Add(item);
28 }
29
30 public void AddOrdered(PackageFacade item)
31 {
32 if (!this.FacadesByPackageId.ContainsKey(item.PackageId))
33 {
34 throw new WixException("Ordered PackageFacade must already exist");
35 }
36
37 this.OrderedFacades.Add(item);
38 }
39
40 public IReadOnlyCollection<PackageFacade> OrderedValues => this.OrderedFacades.AsReadOnly();
41
42 public IEnumerable<PackageFacade> Values => this.FacadesByPackageId.Values;
43
44 public bool TryGetFacadeByPackageId(string packageId, out PackageFacade facade)
45 {
46 return this.FacadesByPackageId.TryGetValue(packageId, out facade);
47 }
48
49 public bool TryGetFacadesByPackagePayloadId(string packagePayloadId, out List<PackageFacade> facades)
50 {
51 return this.FacadesByPackagePayloadId.TryGetValue(packagePayloadId, out facades);
52 }
53 }
54}
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/PerformBundleBackendValidationCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/PerformBundleBackendValidationCommand.cs
index 8a2f1c64..3ffb8df4 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/PerformBundleBackendValidationCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/PerformBundleBackendValidationCommand.cs
@@ -3,7 +3,6 @@
3namespace WixToolset.Core.Burn.Bundles 3namespace WixToolset.Core.Burn.Bundles
4{ 4{
5 using System; 5 using System;
6 using System.Collections.Generic;
7 using WixToolset.Data; 6 using WixToolset.Data;
8 using WixToolset.Data.Symbols; 7 using WixToolset.Data.Symbols;
9 using WixToolset.Extensibility.Data; 8 using WixToolset.Extensibility.Data;
@@ -11,12 +10,12 @@ namespace WixToolset.Core.Burn.Bundles
11 10
12 internal class PerformBundleBackendValidationCommand 11 internal class PerformBundleBackendValidationCommand
13 { 12 {
14 public PerformBundleBackendValidationCommand(IMessaging messaging, IBurnBackendHelper burnBackendHelper, IntermediateSection section, IDictionary<string, PackageFacade> packageFacadesById) 13 public PerformBundleBackendValidationCommand(IMessaging messaging, IBurnBackendHelper burnBackendHelper, IntermediateSection section, PackageFacades packageFacades)
15 { 14 {
16 this.Messaging = messaging; 15 this.Messaging = messaging;
17 this.BackendHelper = burnBackendHelper; 16 this.BackendHelper = burnBackendHelper;
18 this.Section = section; 17 this.Section = section;
19 this.PackageFacadesById = packageFacadesById; 18 this.PackageFacades = packageFacades;
20 } 19 }
21 20
22 private IMessaging Messaging { get; } 21 private IMessaging Messaging { get; }
@@ -25,7 +24,7 @@ namespace WixToolset.Core.Burn.Bundles
25 24
26 private IntermediateSection Section { get; } 25 private IntermediateSection Section { get; }
27 26
28 private IDictionary<string, PackageFacade> PackageFacadesById { get; } 27 private PackageFacades PackageFacades { get; }
29 28
30 public void Execute() 29 public void Execute()
31 { 30 {
@@ -53,7 +52,7 @@ namespace WixToolset.Core.Burn.Bundles
53 } 52 }
54 } 53 }
55 54
56 foreach (var packageFacade in this.PackageFacadesById.Values) 55 foreach (var packageFacade in this.PackageFacades.Values)
57 { 56 {
58 if (packageFacade.SpecificPackageSymbol is WixBundleBundlePackageSymbol wixBundleBundlePackageSymbol) 57 if (packageFacade.SpecificPackageSymbol is WixBundleBundlePackageSymbol wixBundleBundlePackageSymbol)
59 { 58 {
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs
index 2abdec06..47231ccb 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs
@@ -57,8 +57,8 @@ namespace WixToolset.Core.Burn.Bundles
57 public void Execute() 57 public void Execute()
58 { 58 {
59 var harvestedBundlePackage = this.Section.Symbols.OfType<WixBundleHarvestedBundlePackageSymbol>() 59 var harvestedBundlePackage = this.Section.Symbols.OfType<WixBundleHarvestedBundlePackageSymbol>()
60 .Where(h => h.Id == this.ChainPackage.Id) 60 .Where(h => h.Id == this.PackagePayload.Id)
61 .SingleOrDefault(); 61 .SingleOrDefault();
62 62
63 if (harvestedBundlePackage == null) 63 if (harvestedBundlePackage == null)
64 { 64 {
@@ -200,13 +200,12 @@ namespace WixToolset.Core.Burn.Bundles
200 version = registrationElement.GetAttribute("Version"); 200 version = registrationElement.GetAttribute("Version");
201 201
202 var providerKey = registrationElement.GetAttribute("ProviderKey"); 202 var providerKey = registrationElement.GetAttribute("ProviderKey");
203 var depId = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", this.PackageId, providerKey)); 203 var depId = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", this.PackagePayload.Id.Id, providerKey));
204 this.Section.AddSymbol(new WixDependencyProviderSymbol(sourceLineNumbers, depId) 204 this.Section.AddSymbol(new WixBundleHarvestedDependencyProviderSymbol(sourceLineNumbers, depId)
205 { 205 {
206 ParentRef = this.PackageId, 206 PackagePayloadRef = this.PackagePayload.Id.Id,
207 ProviderKey = providerKey, 207 ProviderKey = providerKey,
208 Version = version, 208 Version = version,
209 Attributes = WixDependencyProviderAttributes.ProvidesAttributesImported,
210 }); 209 });
211 210
212 displayName = arpElement.GetAttribute("DisplayName"); 211 displayName = arpElement.GetAttribute("DisplayName");
@@ -224,7 +223,7 @@ namespace WixToolset.Core.Burn.Bundles
224 } 223 }
225 } 224 }
226 225
227 return this.Section.AddSymbol(new WixBundleHarvestedBundlePackageSymbol(this.PackagePayload.SourceLineNumbers, this.ChainPackage.Id) 226 return this.Section.AddSymbol(new WixBundleHarvestedBundlePackageSymbol(this.PackagePayload.SourceLineNumbers, this.PackagePayload.Id)
228 { 227 {
229 Win64 = win64, 228 Win64 = win64,
230 BundleId = bundleId, 229 BundleId = bundleId,
@@ -274,7 +273,7 @@ namespace WixToolset.Core.Burn.Bundles
274 273
275 this.Section.AddSymbol(new WixBundlePackageRelatedBundleSymbol(sourceLineNumbers) 274 this.Section.AddSymbol(new WixBundlePackageRelatedBundleSymbol(sourceLineNumbers)
276 { 275 {
277 PackageRef = this.PackageId, 276 PackagePayloadRef = this.PackagePayload.Id.Id,
278 BundleId = id, 277 BundleId = id,
279 Action = action, 278 Action = action,
280 }); 279 });
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs
index 5acec2a4..0bec201d 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs
@@ -65,7 +65,7 @@ namespace WixToolset.Core.Burn.Bundles
65 public void Execute() 65 public void Execute()
66 { 66 {
67 var harvestedMsiPackage = this.Section.Symbols.OfType<WixBundleHarvestedMsiPackageSymbol>() 67 var harvestedMsiPackage = this.Section.Symbols.OfType<WixBundleHarvestedMsiPackageSymbol>()
68 .Where(h => h.Id == this.ChainPackage.Id) 68 .Where(h => h.Id == this.PackagePayload.Id)
69 .SingleOrDefault(); 69 .SingleOrDefault();
70 70
71 if (harvestedMsiPackage == null) 71 if (harvestedMsiPackage == null)
@@ -78,6 +78,17 @@ namespace WixToolset.Core.Burn.Bundles
78 } 78 }
79 } 79 }
80 80
81 foreach (var childPayload in this.Section.Symbols.OfType<WixBundlePayloadSymbol>().Where(p => p.ParentPackagePayloadRef == this.PackagePayload.Id.Id).ToList())
82 {
83 this.Section.AddSymbol(new WixGroupSymbol(childPayload.SourceLineNumbers)
84 {
85 ParentType = ComplexReferenceParentType.Package,
86 ParentId = this.PackageId,
87 ChildType = ComplexReferenceChildType.Payload,
88 ChildId = childPayload.Id.Id,
89 });
90 }
91
81 this.ChainPackage.PerMachine = harvestedMsiPackage.PerMachine; 92 this.ChainPackage.PerMachine = harvestedMsiPackage.PerMachine;
82 this.ChainPackage.Win64 = harvestedMsiPackage.Win64; 93 this.ChainPackage.Win64 = harvestedMsiPackage.Win64;
83 94
@@ -218,11 +229,7 @@ namespace WixToolset.Core.Burn.Bundles
218 229
219 this.CreateRelatedPackages(db); 230 this.CreateRelatedPackages(db);
220 231
221 // If feature selection is enabled, represent the Feature table in the manifest. 232 this.CreateMsiFeatures(db);
222 if (this.MsiPackage.EnableFeatureSelection)
223 {
224 this.CreateMsiFeatures(db);
225 }
226 233
227 // Add all external cabinets as package payloads. 234 // Add all external cabinets as package payloads.
228 this.ImportExternalCabinetAsPayloads(db, payloadNames); 235 this.ImportExternalCabinetAsPayloads(db, payloadNames);
@@ -241,7 +248,7 @@ namespace WixToolset.Core.Burn.Bundles
241 return null; 248 return null;
242 } 249 }
243 250
244 return this.Section.AddSymbol(new WixBundleHarvestedMsiPackageSymbol(this.PackagePayload.SourceLineNumbers, this.ChainPackage.Id) 251 return this.Section.AddSymbol(new WixBundleHarvestedMsiPackageSymbol(this.PackagePayload.SourceLineNumbers, this.PackagePayload.Id)
245 { 252 {
246 PerMachine = perMachine, 253 PerMachine = perMachine,
247 Win64 = win64, 254 Win64 = win64,
@@ -379,7 +386,7 @@ namespace WixToolset.Core.Burn.Bundles
379 386
380 this.Section.AddSymbol(new WixBundleRelatedPackageSymbol(this.PackagePayload.SourceLineNumbers) 387 this.Section.AddSymbol(new WixBundleRelatedPackageSymbol(this.PackagePayload.SourceLineNumbers)
381 { 388 {
382 PackageRef = this.PackageId, 389 PackagePayloadRef = this.PackagePayload.Id.Id,
383 RelatedId = record.GetString(1), 390 RelatedId = record.GetString(1),
384 MinVersion = record.GetString(2), 391 MinVersion = record.GetString(2),
385 MaxVersion = record.GetString(3), 392 MaxVersion = record.GetString(3),
@@ -425,9 +432,9 @@ namespace WixToolset.Core.Burn.Bundles
425 } 432 }
426 } 433 }
427 434
428 this.Section.AddSymbol(new WixBundleMsiFeatureSymbol(this.PackagePayload.SourceLineNumbers, new Identifier(AccessModifier.Section, this.PackageId, featureName)) 435 this.Section.AddSymbol(new WixBundleMsiFeatureSymbol(this.PackagePayload.SourceLineNumbers, new Identifier(AccessModifier.Section, this.PackagePayload.Id.Id, featureName))
429 { 436 {
430 PackageRef = this.PackageId, 437 PackagePayloadRef = this.PackagePayload.Id.Id,
431 Name = featureName, 438 Name = featureName,
432 Parent = allFeaturesResultRecord.GetString(2), 439 Parent = allFeaturesResultRecord.GetString(2),
433 Title = allFeaturesResultRecord.GetString(3), 440 Title = allFeaturesResultRecord.GetString(3),
@@ -468,14 +475,6 @@ namespace WixToolset.Core.Burn.Bundles
468 var generatedId = this.BackendHelper.GenerateIdentifier("cab", this.PackagePayload.Id.Id, cabinet); 475 var generatedId = this.BackendHelper.GenerateIdentifier("cab", this.PackagePayload.Id.Id, cabinet);
469 var payloadSourceFile = this.ResolveRelatedFile(this.PackagePayload.SourceFile.Path, this.PackagePayload.UnresolvedSourceFile, cabinet, "Cabinet", sourceLineNumbers); 476 var payloadSourceFile = this.ResolveRelatedFile(this.PackagePayload.SourceFile.Path, this.PackagePayload.UnresolvedSourceFile, cabinet, "Cabinet", sourceLineNumbers);
470 477
471 this.Section.AddSymbol(new WixGroupSymbol(sourceLineNumbers)
472 {
473 ParentType = ComplexReferenceParentType.Package,
474 ParentId = this.PackageId,
475 ChildType = ComplexReferenceChildType.Payload,
476 ChildId = generatedId
477 });
478
479 this.Section.AddSymbol(new WixBundlePayloadSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, generatedId)) 478 this.Section.AddSymbol(new WixBundlePayloadSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, generatedId))
480 { 479 {
481 Name = cabinetName, 480 Name = cabinetName,
@@ -540,14 +539,6 @@ namespace WixToolset.Core.Burn.Bundles
540 var generatedId = this.BackendHelper.GenerateIdentifier("f", this.PackagePayload.Id.Id, record.GetString(2)); 539 var generatedId = this.BackendHelper.GenerateIdentifier("f", this.PackagePayload.Id.Id, record.GetString(2));
541 var payloadSourceFile = this.ResolveRelatedFile(this.PackagePayload.SourceFile.Path, this.PackagePayload.UnresolvedSourceFile, fileSourcePath, "File", sourceLineNumbers); 540 var payloadSourceFile = this.ResolveRelatedFile(this.PackagePayload.SourceFile.Path, this.PackagePayload.UnresolvedSourceFile, fileSourcePath, "File", sourceLineNumbers);
542 541
543 this.Section.AddSymbol(new WixGroupSymbol(sourceLineNumbers)
544 {
545 ParentType = ComplexReferenceParentType.Package,
546 ParentId = this.PackageId,
547 ChildType = ComplexReferenceChildType.Payload,
548 ChildId = generatedId
549 });
550
551 this.Section.AddSymbol(new WixBundlePayloadSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, generatedId)) 542 this.Section.AddSymbol(new WixBundlePayloadSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, generatedId))
552 { 543 {
553 Name = name, 544 Name = name,
@@ -594,16 +585,16 @@ namespace WixToolset.Core.Burn.Bundles
594 { 585 {
595 foreach (var record in view.Records) 586 foreach (var record in view.Records)
596 { 587 {
597 var id = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", this.PackageId, record.GetString(1))); 588 var id = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", this.PackagePayload.Id.Id, record.GetString(1)));
598 589
599 // Import the provider key and attributes. 590 // Import the provider key and attributes.
600 this.Section.AddSymbol(new WixDependencyProviderSymbol(this.PackagePayload.SourceLineNumbers, id) 591 this.Section.AddSymbol(new WixBundleHarvestedDependencyProviderSymbol(this.PackagePayload.SourceLineNumbers, id)
601 { 592 {
602 ParentRef = this.PackageId, 593 PackagePayloadRef = this.PackagePayload.Id.Id,
603 ProviderKey = record.GetString(2), 594 ProviderKey = record.GetString(2),
604 Version = record.GetString(3) ?? this.MsiPackage.ProductVersion, 595 Version = record.GetString(3) ?? this.MsiPackage.ProductVersion,
605 DisplayName = record.GetString(4) ?? this.ChainPackage.DisplayName, 596 DisplayName = record.GetString(4) ?? this.ChainPackage.DisplayName,
606 Attributes = WixDependencyProviderAttributes.ProvidesAttributesImported | (WixDependencyProviderAttributes)record.GetInteger(5), 597 ProviderAttributes = record.GetInteger(5),
607 }); 598 });
608 } 599 }
609 } 600 }
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs
index cef68c8a..466ef5b9 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs
@@ -53,7 +53,7 @@ namespace WixToolset.Core.Burn.Bundles
53 public void Execute() 53 public void Execute()
54 { 54 {
55 var harvestedMspPackage = this.Section.Symbols.OfType<WixBundleHarvestedMspPackageSymbol>() 55 var harvestedMspPackage = this.Section.Symbols.OfType<WixBundleHarvestedMspPackageSymbol>()
56 .Where(h => h.Id == this.ChainPackage.Id) 56 .Where(h => h.Id == this.PackagePayload.Id)
57 .SingleOrDefault(); 57 .SingleOrDefault();
58 58
59 if (harvestedMspPackage == null) 59 if (harvestedMspPackage == null)
@@ -123,7 +123,7 @@ namespace WixToolset.Core.Burn.Bundles
123 return null; 123 return null;
124 } 124 }
125 125
126 return this.Section.AddSymbol(new WixBundleHarvestedMspPackageSymbol(this.PackagePayload.SourceLineNumbers, this.ChainPackage.Id) 126 return this.Section.AddSymbol(new WixBundleHarvestedMspPackageSymbol(this.PackagePayload.SourceLineNumbers, this.PackagePayload.Id)
127 { 127 {
128 PatchCode = patchCode, 128 PatchCode = patchCode,
129 DisplayName = displayName, 129 DisplayName = displayName,
@@ -175,7 +175,7 @@ namespace WixToolset.Core.Burn.Bundles
175 { 175 {
176 var symbol = section.AddSymbol(new WixBundlePatchTargetCodeSymbol(sourceLineNumbers) 176 var symbol = section.AddSymbol(new WixBundlePatchTargetCodeSymbol(sourceLineNumbers)
177 { 177 {
178 PackageRef = id.Id, 178 PackagePayloadRef = id.Id,
179 TargetCode = targetCode, 179 TargetCode = targetCode,
180 Attributes = 0, 180 Attributes = 0,
181 Type = type, 181 Type = type,
diff --git a/src/wix/WixToolset.Core.Burn/BurnBackendErrors.cs b/src/wix/WixToolset.Core.Burn/BurnBackendErrors.cs
index bf07fad2..0cfd849b 100644
--- a/src/wix/WixToolset.Core.Burn/BurnBackendErrors.cs
+++ b/src/wix/WixToolset.Core.Burn/BurnBackendErrors.cs
@@ -17,6 +17,11 @@ namespace WixToolset.Core.Burn
17 return Message(sourceLineNumbers, Ids.BAContainerPayloadCollision2, "The location of the payload related to the previous error."); 17 return Message(sourceLineNumbers, Ids.BAContainerPayloadCollision2, "The location of the payload related to the previous error.");
18 } 18 }
19 19
20 public static Message BundleMultipleProviders(SourceLineNumber sourceLineNumbers, string extraProviderKey, string originalProviderKey)
21 {
22 return Message(sourceLineNumbers, Ids.BundleMultipleProviders, "The bundle can only have a single dependency provider, but it has '{0}' and '{1}'.", originalProviderKey, extraProviderKey);
23 }
24
20 public static Message DuplicateCacheIds(SourceLineNumber originalLineNumber, string cacheId, string packageId) 25 public static Message DuplicateCacheIds(SourceLineNumber originalLineNumber, string cacheId, string packageId)
21 { 26 {
22 return Message(originalLineNumber, Ids.DuplicateCacheIds, "The CacheId '{0}' for package '{1}' is duplicated. Each package must have a unique CacheId.", cacheId, packageId); 27 return Message(originalLineNumber, Ids.DuplicateCacheIds, "The CacheId '{0}' for package '{1}' is duplicated. Each package must have a unique CacheId.", cacheId, packageId);
@@ -110,6 +115,7 @@ namespace WixToolset.Core.Burn
110 UnsupportedRemotePackagePayload = 8010, 115 UnsupportedRemotePackagePayload = 8010,
111 FailedToAddIconOrSplashScreenToBundle = 8011, 116 FailedToAddIconOrSplashScreenToBundle = 8011,
112 InvalidBundleManifest = 8012, 117 InvalidBundleManifest = 8012,
118 BundleMultipleProviders = 8013,
113 } // last available is 8499. 8500 is BurnBackendWarnings. 119 } // last available is 8499. 8500 is BurnBackendWarnings.
114 } 120 }
115} 121}
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/PackagePayloadFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/PackagePayloadFixture.cs
index 6db96dbc..3dead50d 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/PackagePayloadFixture.cs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/PackagePayloadFixture.cs
@@ -5,6 +5,7 @@ namespace WixToolsetTest.CoreIntegration
5 using System.Collections.Generic; 5 using System.Collections.Generic;
6 using System.IO; 6 using System.IO;
7 using System.Linq; 7 using System.Linq;
8 using System.Xml;
8 using WixBuildTools.TestSupport; 9 using WixBuildTools.TestSupport;
9 using WixToolset.Core.TestPackage; 10 using WixToolset.Core.TestPackage;
10 using Xunit; 11 using Xunit;
@@ -12,6 +13,83 @@ namespace WixToolsetTest.CoreIntegration
12 public class PackagePayloadFixture 13 public class PackagePayloadFixture
13 { 14 {
14 [Fact] 15 [Fact]
16 public void CanSpecifyMsiPackagePayloadInPayloadGroup()
17 {
18 var folder = TestData.Get(@"TestData");
19
20 using (var fs = new DisposableFileSystem())
21 {
22 var baseFolder = fs.GetFolder();
23 var intermediateFolder = Path.Combine(baseFolder, "obj");
24 var bundlePath = Path.Combine(baseFolder, @"bin\test.exe");
25 var baFolderPath = Path.Combine(baseFolder, "ba");
26 var extractFolderPath = Path.Combine(baseFolder, "extract");
27
28 var result = WixRunner.Execute(new[]
29 {
30 "build",
31 Path.Combine(folder, "PackagePayload", "MsiPackagePayloadInPayloadGroup.wxs"),
32 Path.Combine(folder, "BundleWithPackageGroupRef", "Bundle.wxs"),
33 "-bindpath", Path.Combine(folder, "SimpleBundle", "data"),
34 "-bindpath", Path.Combine(folder, ".Data"),
35 "-intermediateFolder", intermediateFolder,
36 "-o", bundlePath,
37 });
38
39 result.AssertSuccess();
40
41 Assert.True(File.Exists(bundlePath));
42
43 var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath);
44 extractResult.AssertSuccess();
45
46 var ignoreAttributesByElementName = new Dictionary<string, List<string>>
47 {
48 { "ExePackage", new List<string> { "CacheId", "InstallSize", "Size" } },
49 };
50 var msiPackageElements = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Chain/burn:MsiPackage")
51 .Cast<XmlElement>()
52 .Select(e => e.GetTestXml(ignoreAttributesByElementName))
53 .ToArray();
54 WixAssert.CompareLineByLine(new[]
55 {
56 "<MsiPackage Id='MsiWithFeatures' Cache='keep' CacheId='{040011E1-F84C-4927-AD62-50A5EC19CA32}v1.0.0.0_1' InstallSize='34' Size='32803' PerMachine='yes' Permanent='no' Vital='yes' RollbackBoundaryForward='WixDefaultBoundary' LogPathVariable='WixBundleLog_MsiWithFeatures' RollbackLogPathVariable='WixBundleRollbackLog_MsiWithFeatures' ProductCode='{040011E1-F84C-4927-AD62-50A5EC19CA32}' Language='1033' Version='1.0.0.0' UpgradeCode='{047730A5-30FE-4A62-A520-DA9381B8226A}'>" +
57 "<MsiFeature Id='ProductFeature' /><MsiProperty Id='ARPSYSTEMCOMPONENT' Value='1' /><MsiProperty Id='MSIFASTINSTALL' Value='7' /><Provides Key='{040011E1-F84C-4927-AD62-50A5EC19CA32}_v1.0.0.0' Version='1.0.0.0' DisplayName='MsiPackage' />" +
58 "<RelatedPackage Id='{047730A5-30FE-4A62-A520-DA9381B8226A}' MaxVersion='1.0.0.0' MaxInclusive='no' OnlyDetect='no' LangInclusive='yes'><Language Id='1033' /></RelatedPackage>" +
59 "<RelatedPackage Id='{047730A5-30FE-4A62-A520-DA9381B8226A}' MinVersion='1.0.0.0' MinInclusive='no' OnlyDetect='yes' LangInclusive='yes'><Language Id='1033' /></RelatedPackage>" +
60 "<PayloadRef Id='test.msi' /><PayloadRef Id='fhuZsOcBDTuIX8rF96kswqI6SnuI' /><PayloadRef Id='faf_OZ741BG7SJ6ZkcIvivZ2Yzo8' />" +
61 "</MsiPackage>",
62
63 "<MsiPackage Id='MsiWithoutFeatures' Cache='keep' CacheId='{040011E1-F84C-4927-AD62-50A5EC19CA32}v1.0.0.0_2' InstallSize='34' Size='32803' PerMachine='yes' Permanent='no' Vital='yes' RollbackBoundaryBackward='WixDefaultBoundary' LogPathVariable='WixBundleLog_MsiWithoutFeatures' RollbackLogPathVariable='WixBundleRollbackLog_MsiWithoutFeatures' ProductCode='{040011E1-F84C-4927-AD62-50A5EC19CA32}' Language='1033' Version='1.0.0.0' UpgradeCode='{047730A5-30FE-4A62-A520-DA9381B8226A}'>" +
64 "<MsiProperty Id='ARPSYSTEMCOMPONENT' Value='1' /><MsiProperty Id='MSIFASTINSTALL' Value='7' /><Provides Key='{040011E1-F84C-4927-AD62-50A5EC19CA32}_v1.0.0.0' Version='1.0.0.0' DisplayName='MsiPackage' />" +
65 "<RelatedPackage Id='{047730A5-30FE-4A62-A520-DA9381B8226A}' MaxVersion='1.0.0.0' MaxInclusive='no' OnlyDetect='no' LangInclusive='yes'><Language Id='1033' /></RelatedPackage>" +
66 "<RelatedPackage Id='{047730A5-30FE-4A62-A520-DA9381B8226A}' MinVersion='1.0.0.0' MinInclusive='no' OnlyDetect='yes' LangInclusive='yes'><Language Id='1033' /></RelatedPackage>" +
67 "<PayloadRef Id='test.msi' /><PayloadRef Id='fhuZsOcBDTuIX8rF96kswqI6SnuI' /><PayloadRef Id='faf_OZ741BG7SJ6ZkcIvivZ2Yzo8' />" +
68 "</MsiPackage>",
69 }, msiPackageElements);
70
71 var packageElements = extractResult.SelectBADataNodes("/ba:BootstrapperApplicationData/ba:WixPackageProperties")
72 .Cast<XmlElement>()
73 .Select(e => e.GetTestXml())
74 .ToArray();
75 WixAssert.CompareLineByLine(new []
76 {
77 "<WixPackageProperties Package='MsiWithFeatures' Vital='yes' DisplayName='MsiPackage' DownloadSize='32803' PackageSize='32803' InstalledSize='34' PackageType='Msi' Permanent='no' LogPathVariable='WixBundleLog_MsiWithFeatures' RollbackLogPathVariable='WixBundleRollbackLog_MsiWithFeatures' Compressed='yes' ProductCode='{040011E1-F84C-4927-AD62-50A5EC19CA32}' UpgradeCode='{047730A5-30FE-4A62-A520-DA9381B8226A}' Version='1.0.0.0' Cache='keep' />",
78 "<WixPackageProperties Package='MsiWithoutFeatures' Vital='yes' DisplayName='MsiPackage' DownloadSize='32803' PackageSize='32803' InstalledSize='34' PackageType='Msi' Permanent='no' LogPathVariable='WixBundleLog_MsiWithoutFeatures' RollbackLogPathVariable='WixBundleRollbackLog_MsiWithoutFeatures' Compressed='yes' ProductCode='{040011E1-F84C-4927-AD62-50A5EC19CA32}' UpgradeCode='{047730A5-30FE-4A62-A520-DA9381B8226A}' Version='1.0.0.0' Cache='keep' />",
79 }, packageElements);
80
81 var featureElements = extractResult.SelectBADataNodes("/ba:BootstrapperApplicationData/ba:WixPackageFeatureInfo")
82 .Cast<XmlElement>()
83 .Select(e => e.GetTestXml())
84 .ToArray();
85 WixAssert.CompareLineByLine(new[]
86 {
87 "<WixPackageFeatureInfo Package='MsiWithFeatures' Feature='ProductFeature' Size='34' Display='2' Level='1' Directory='' Attributes='0' />",
88 }, featureElements);
89 }
90 }
91
92 [Fact]
15 public void CanSpecifyPackagePayloadInPayloadGroup() 93 public void CanSpecifyPackagePayloadInPayloadGroup()
16 { 94 {
17 var folder = TestData.Get(@"TestData"); 95 var folder = TestData.Get(@"TestData");
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PackagePayload/MsiPackagePayloadInPayloadGroup.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PackagePayload/MsiPackagePayloadInPayloadGroup.wxs
new file mode 100644
index 00000000..1fa7b7e6
--- /dev/null
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/PackagePayload/MsiPackagePayloadInPayloadGroup.wxs
@@ -0,0 +1,18 @@
1<?xml version="1.0" encoding="utf-8"?>
2<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
3 <Fragment>
4 <PackageGroup Id="BundlePackages">
5 <MsiPackage Id="MsiWithFeatures" CacheId="{040011E1-F84C-4927-AD62-50A5EC19CA32}v1.0.0.0_1" EnableFeatureSelection="yes">
6 <PayloadGroupRef Id="PackagePayloadGroup" />
7 </MsiPackage>
8 <MsiPackage Id="MsiWithoutFeatures" CacheId="{040011E1-F84C-4927-AD62-50A5EC19CA32}v1.0.0.0_2">
9 <PayloadGroupRef Id="PackagePayloadGroup" />
10 </MsiPackage>
11 </PackageGroup>
12 </Fragment>
13 <Fragment>
14 <PayloadGroup Id="PackagePayloadGroup">
15 <MsiPackagePayload SourceFile="test.msi" />
16 </PayloadGroup>
17 </Fragment>
18</Wix>