Add bundle support to "burn remotepayload" command.
Sean Hall committed
Apr 13, 2022 at 12:17 UTC
535e4165e3121a14e5799f575a1010671212c539
7 files changed
+379
-206
src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
+2
@@ -182,6 +182,8 @@ namespace WixToolset.Core.Burn
182
{
183
var command = new ProcessBundlePackageCommand(this.ServiceProvider, section, facade, packagesPayloads[facade.PackageId], this.IntermediateFolder);
184
command.Execute();
185
+
186
+ trackedFiles.AddRange(command.TrackedFiles);
187
}
188
break;
189
src/wix/WixToolset.Core.Burn/Bundles/HarvestBundlePackageCommand.cs
new
+248
@@ -0,0 +1,248 @@
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
+
3
+namespace WixToolset.Core.Burn.Bundles
4
+{
5
+ using System;
6
+ using System.Collections.Generic;
7
+ using System.IO;
8
+ using System.Text;
9
+ using System.Xml;
10
+ using WixToolset.Data;
11
+ using WixToolset.Data.Symbols;
12
+ using WixToolset.Extensibility.Data;
13
+ using WixToolset.Extensibility.Services;
14
+
15
+ internal class HarvestBundlePackageCommand
16
+ {
17
+ public HarvestBundlePackageCommand(IServiceProvider serviceProvider, string intermediateFolder, WixBundlePayloadSymbol payloadSymbol)
18
+ {
19
+ this.Messaging = serviceProvider.GetService<IMessaging>();
20
+ this.BackendHelper = serviceProvider.GetService<IBackendHelper>();
21
+ this.IntermediateFolder = intermediateFolder;
22
+
23
+ this.PackagePayload = payloadSymbol;
24
+ }
25
+
26
+ private IMessaging Messaging { get; }
27
+
28
+ private IBackendHelper BackendHelper { get; }
29
+
30
+ private string IntermediateFolder { get; }
31
+
32
+ private WixBundlePayloadSymbol PackagePayload { get; }
33
+
34
+ public WixBundleHarvestedBundlePackageSymbol HarvestedBundlePackage { get; private set; }
35
+
36
+ public WixBundleHarvestedDependencyProviderSymbol HarvestedDependencyProvider { get; private set; }
37
+
38
+ public List<WixBundlePackageRelatedBundleSymbol> RelatedBundles { get; } = new List<WixBundlePackageRelatedBundleSymbol>();
39
+
40
+ public List<ITrackedFile> TrackedFiles { get; } = new List<ITrackedFile>();
41
+
42
+ public void Execute()
43
+ {
44
+ bool win64;
45
+ string bundleId;
46
+ string engineVersion;
47
+ int protocolVersion;
48
+ string manifestNamespace;
49
+ bool perMachine;
50
+ string version;
51
+ string displayName;
52
+ long installSize;
53
+
54
+ var sourcePath = this.PackagePayload.SourceFile.Path;
55
+ var sourceLineNumbers = this.PackagePayload.SourceLineNumbers;
56
+
57
+ using (var burnReader = BurnReader.Open(this.Messaging, sourcePath))
58
+ {
59
+ if (burnReader.Invalid)
60
+ {
61
+ return;
62
+ }
63
+
64
+ var baFolderPath = Path.Combine(this.IntermediateFolder, burnReader.BundleId.ToString());
65
+
66
+ if (!burnReader.ExtractUXContainer(baFolderPath, baFolderPath))
67
+ {
68
+ return;
69
+ }
70
+
71
+ foreach (var filePath in Directory.EnumerateFiles(baFolderPath, "*.*", SearchOption.AllDirectories))
72
+ {
73
+ this.TrackedFiles.Add(this.BackendHelper.TrackFile(filePath, TrackedFileType.Temporary, sourceLineNumbers));
74
+ }
75
+
76
+ bundleId = burnReader.BundleId.ToString("B").ToUpperInvariant();
77
+
78
+ try
79
+ {
80
+ var document = new XmlDocument();
81
+ document.Load(Path.Combine(baFolderPath, "manifest.xml"));
82
+ var namespaceManager = new XmlNamespaceManager(document.NameTable);
83
+
84
+ if (document.DocumentElement.LocalName != "BurnManifest")
85
+ {
86
+ this.Messaging.Write(BurnBackendErrors.InvalidBundleManifest(sourceLineNumbers, sourcePath, $"Expected root element to be 'BurnManifest' but was '{document.DocumentElement.LocalName}'."));
87
+ return;
88
+ }
89
+
90
+ engineVersion = document.DocumentElement.GetAttribute("EngineVersion");
91
+ protocolVersion = this.ProcessProtocolVersion(burnReader, document);
92
+ win64 = this.ProcessWin64(burnReader, document, sourceLineNumbers, sourcePath);
93
+
94
+ manifestNamespace = document.DocumentElement.NamespaceURI;
95
+
96
+ namespaceManager.AddNamespace("burn", document.DocumentElement.NamespaceURI);
97
+ var registrationElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration", namespaceManager) as XmlElement;
98
+ var arpElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration/burn:Arp", namespaceManager) as XmlElement;
99
+
100
+ perMachine = registrationElement.GetAttribute("PerMachine") == "yes";
101
+
102
+ version = registrationElement.GetAttribute("Version");
103
+
104
+ var providerKey = registrationElement.GetAttribute("ProviderKey");
105
+ var depId = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", this.PackagePayload.Id.Id, providerKey));
106
+ this.HarvestedDependencyProvider = new WixBundleHarvestedDependencyProviderSymbol(sourceLineNumbers, depId)
107
+ {
108
+ PackagePayloadRef = this.PackagePayload.Id.Id,
109
+ ProviderKey = providerKey,
110
+ Version = version,
111
+ };
112
+
113
+ displayName = arpElement.GetAttribute("DisplayName");
114
+
115
+ installSize = this.ProcessPackages(document, namespaceManager);
116
+
117
+ this.ProcessRelatedBundles(document, namespaceManager, sourcePath);
118
+
119
+ // TODO: Add payloads?
120
+ }
121
+ catch (Exception e)
122
+ {
123
+ this.Messaging.Write(BurnBackendErrors.InvalidBundleManifest(sourceLineNumbers, sourcePath, e.ToString()));
124
+ return;
125
+ }
126
+ }
127
+
128
+ this.HarvestedBundlePackage = new WixBundleHarvestedBundlePackageSymbol(this.PackagePayload.SourceLineNumbers, this.PackagePayload.Id)
129
+ {
130
+ Win64 = win64,
131
+ BundleId = bundleId,
132
+ EngineVersion = engineVersion,
133
+ ManifestNamespace = manifestNamespace,
134
+ ProtocolVersion = protocolVersion,
135
+ PerMachine = perMachine,
136
+ Version = version,
137
+ DisplayName = displayName,
138
+ InstallSize = installSize,
139
+ };
140
+ }
141
+
142
+ private int ProcessProtocolVersion(BurnReader burnReader, XmlDocument document)
143
+ {
144
+ var protocolVersionValue = document.DocumentElement.GetAttribute("ProtocolVersion");
145
+
146
+ if (Int32.TryParse(protocolVersionValue, out var protocolVersion))
147
+ {
148
+ return protocolVersion;
149
+ }
150
+
151
+ // Assume that the .wixburn section version will change when the Burn protocol changes.
152
+ // This should be a safe assumption since only old bundles should be missing the ProtocolVersion from the manifest.
153
+ return burnReader.Version == 2 ? 1 : 0;
154
+ }
155
+
156
+ private bool ProcessWin64(BurnReader burnReader, XmlDocument document, SourceLineNumber sourceLineNumbers, string sourcePath)
157
+ {
158
+ var win64Value = document.DocumentElement.GetAttribute("Win64");
159
+
160
+ switch (win64Value)
161
+ {
162
+ case "yes":
163
+ return true;
164
+ case "no":
165
+ return false;
166
+ }
167
+
168
+ switch (burnReader.MachineType)
169
+ {
170
+ case BurnCommon.IMAGE_FILE_MACHINE_ARM:
171
+ case BurnCommon.IMAGE_FILE_MACHINE_ARMNT:
172
+ case BurnCommon.IMAGE_FILE_MACHINE_I386:
173
+ case BurnCommon.IMAGE_FILE_MACHINE_LOONGARCH32:
174
+ return false;
175
+ case BurnCommon.IMAGE_FILE_MACHINE_AMD64:
176
+ case BurnCommon.IMAGE_FILE_MACHINE_ARM64:
177
+ case BurnCommon.IMAGE_FILE_MACHINE_IA64:
178
+ case BurnCommon.IMAGE_FILE_MACHINE_LOONGARCH64:
179
+ return true;
180
+ case BurnCommon.IMAGE_FILE_MACHINE_AM33:
181
+ case BurnCommon.IMAGE_FILE_MACHINE_EBC:
182
+ case BurnCommon.IMAGE_FILE_MACHINE_M32R:
183
+ case BurnCommon.IMAGE_FILE_MACHINE_MIPS16:
184
+ case BurnCommon.IMAGE_FILE_MACHINE_MIPSFPU:
185
+ case BurnCommon.IMAGE_FILE_MACHINE_MIPSFPU16:
186
+ case BurnCommon.IMAGE_FILE_MACHINE_POWERPC:
187
+ case BurnCommon.IMAGE_FILE_MACHINE_POWERPCFP:
188
+ case BurnCommon.IMAGE_FILE_MACHINE_R4000:
189
+ case BurnCommon.IMAGE_FILE_MACHINE_RISCV32:
190
+ case BurnCommon.IMAGE_FILE_MACHINE_RISCV64:
191
+ case BurnCommon.IMAGE_FILE_MACHINE_RISCV128:
192
+ case BurnCommon.IMAGE_FILE_MACHINE_SH3:
193
+ case BurnCommon.IMAGE_FILE_MACHINE_SH3DSP:
194
+ case BurnCommon.IMAGE_FILE_MACHINE_SH4:
195
+ case BurnCommon.IMAGE_FILE_MACHINE_SH5:
196
+ case BurnCommon.IMAGE_FILE_MACHINE_THUMB:
197
+ case BurnCommon.IMAGE_FILE_MACHINE_WCEMIPSV2:
198
+ default:
199
+ this.Messaging.Write(BurnBackendWarnings.UnknownCoffMachineType(sourceLineNumbers, sourcePath, burnReader.MachineType));
200
+ return false;
201
+ }
202
+ }
203
+
204
+ private long ProcessPackages(XmlDocument document, XmlNamespaceManager namespaceManager)
205
+ {
206
+ long packageInstallSize = 0;
207
+
208
+ foreach (XmlElement packageElement in document.SelectNodes("/burn:BurnManifest/burn:Chain/*", namespaceManager))
209
+ {
210
+ if (!packageElement.Name.EndsWith("Package"))
211
+ {
212
+ continue;
213
+ }
214
+
215
+ if (Int64.TryParse(packageElement.GetAttribute("InstallSize"), out var installSize))
216
+ {
217
+ packageInstallSize += installSize;
218
+ }
219
+ }
220
+
221
+ return packageInstallSize;
222
+ }
223
+
224
+ private void ProcessRelatedBundles(XmlDocument document, XmlNamespaceManager namespaceManager, string sourcePath)
225
+ {
226
+ var sourceLineNumbers = this.PackagePayload.SourceLineNumbers;
227
+
228
+ foreach (XmlElement relatedBundleElement in document.SelectNodes("/burn:BurnManifest/burn:RelatedBundle", namespaceManager))
229
+ {
230
+ var id = relatedBundleElement.GetAttribute("Id");
231
+ var actionValue = relatedBundleElement.GetAttribute("Action");
232
+
233
+ if (!Enum.TryParse(actionValue, out RelatedBundleActionType action))
234
+ {
235
+ this.Messaging.Write(BurnBackendWarnings.UnknownBundleRelationAction(sourceLineNumbers, sourcePath, actionValue));
236
+ continue;
237
+ }
238
+
239
+ this.RelatedBundles.Add(new WixBundlePackageRelatedBundleSymbol(sourceLineNumbers)
240
+ {
241
+ PackagePayloadRef = this.PackagePayload.Id.Id,
242
+ BundleId = id,
243
+ Action = action,
244
+ });
245
+ }
246
+ }
247
+ }
248
+}
src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs
+14
-201
@@ -4,10 +4,7 @@ namespace WixToolset.Core.Burn.Bundles
4
{
5
using System;
6
using System.Collections.Generic;
7
- using System.Diagnostics;
8
- using System.IO;
7
using System.Linq;
10
- using System.Xml;
8
using WixToolset.Data;
9
using WixToolset.Data.Symbols;
10
using WixToolset.Extensibility.Data;
@@ -20,8 +17,8 @@ namespace WixToolset.Core.Burn.Bundles
17
{
18
public ProcessBundlePackageCommand(IServiceProvider serviceProvider, IntermediateSection section, PackageFacade facade, Dictionary<string, WixBundlePayloadSymbol> packagePayloads, string intermediateFolder)
19
{
20
+ this.ServiceProvider = serviceProvider;
21
this.Messaging = serviceProvider.GetService<IMessaging>();
24
- this.BackendHelper = serviceProvider.GetService<IBackendHelper>();
22
this.PackagePayloads = packagePayloads;
23
this.Section = section;
24
this.IntermediateFolder = intermediateFolder;
@@ -31,9 +28,9 @@ namespace WixToolset.Core.Burn.Bundles
28
this.PackagePayload = packagePayloads[this.ChainPackage.PayloadRef];
29
}
30
34
- private IMessaging Messaging { get; }
31
+ private IServiceProvider ServiceProvider { get; }
32
36
- private IBackendHelper BackendHelper { get; }
33
+ private IMessaging Messaging { get; }
34
35
private Dictionary<string, WixBundlePayloadSymbol> PackagePayloads { get; }
36
@@ -101,210 +98,26 @@ namespace WixToolset.Core.Burn.Bundles
98
this.ChainPackage.InstallSize = harvestedBundlePackage.InstallSize;
99
}
100
104
- public WixBundleHarvestedBundlePackageSymbol HarvestPackage()
101
+ private WixBundleHarvestedBundlePackageSymbol HarvestPackage()
102
{
106
- bool win64;
107
- string bundleId;
108
- string engineVersion;
109
- int protocolVersion;
110
- string manifestNamespace;
111
- bool perMachine;
112
- string version;
113
- string displayName;
114
- long installSize;
115
-
116
- var sourcePath = this.PackagePayload.SourceFile.Path;
117
- var sourceLineNumbers = this.PackagePayload.SourceLineNumbers;
103
+ var command = new HarvestBundlePackageCommand(this.ServiceProvider, this.IntermediateFolder, this.PackagePayload);
104
+ command.Execute();
105
119
- using (var burnReader = BurnReader.Open(this.Messaging, sourcePath))
106
+ this.TrackedFiles.AddRange(command.TrackedFiles);
107
+ if (this.Messaging.EncounteredError)
108
{
121
- if (burnReader.Invalid)
122
- {
123
- return null;
124
- }
125
-
126
- var baFolderPath = Path.Combine(this.IntermediateFolder, burnReader.BundleId.ToString());
127
-
128
- if (!burnReader.ExtractUXContainer(baFolderPath, baFolderPath))
129
- {
130
- return null;
131
- }
132
-
133
- foreach (var filePath in Directory.EnumerateFiles(baFolderPath, "*.*", SearchOption.AllDirectories))
134
- {
135
- this.TrackedFiles.Add(this.BackendHelper.TrackFile(filePath, TrackedFileType.Temporary, sourceLineNumbers));
136
- }
137
-
138
- bundleId = burnReader.BundleId.ToString("B").ToUpperInvariant();
139
-
140
- try
141
- {
142
- var document = new XmlDocument();
143
- document.Load(Path.Combine(baFolderPath, "manifest.xml"));
144
- var namespaceManager = new XmlNamespaceManager(document.NameTable);
145
-
146
- if (document.DocumentElement.LocalName != "BurnManifest")
147
- {
148
- this.Messaging.Write(BurnBackendErrors.InvalidBundleManifest(sourceLineNumbers, sourcePath, $"Expected root element to be 'BurnManifest' but was '{document.DocumentElement.LocalName}'."));
149
- return null;
150
- }
151
-
152
- engineVersion = document.DocumentElement.GetAttribute("EngineVersion");
153
- protocolVersion = this.ProcessProtocolVersion(burnReader, document);
154
- win64 = this.ProcessWin64(burnReader, document, sourceLineNumbers, sourcePath);
155
-
156
- manifestNamespace = document.DocumentElement.NamespaceURI;
157
-
158
- namespaceManager.AddNamespace("burn", document.DocumentElement.NamespaceURI);
159
- var registrationElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration", namespaceManager) as XmlElement;
160
- var arpElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration/burn:Arp", namespaceManager) as XmlElement;
161
-
162
- perMachine = registrationElement.GetAttribute("PerMachine") == "yes";
163
-
164
- version = registrationElement.GetAttribute("Version");
165
-
166
- var providerKey = registrationElement.GetAttribute("ProviderKey");
167
- var depId = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", this.PackagePayload.Id.Id, providerKey));
168
- this.Section.AddSymbol(new WixBundleHarvestedDependencyProviderSymbol(sourceLineNumbers, depId)
169
- {
170
- PackagePayloadRef = this.PackagePayload.Id.Id,
171
- ProviderKey = providerKey,
172
- Version = version,
173
- });
174
-
175
- displayName = arpElement.GetAttribute("DisplayName");
176
-
177
- installSize = this.ProcessPackages(document, namespaceManager);
178
-
179
- this.ProcessRelatedBundles(document, namespaceManager, sourcePath);
180
-
181
- // TODO: Add payloads?
182
- }
183
- catch (Exception e)
184
- {
185
- this.Messaging.Write(BurnBackendErrors.InvalidBundleManifest(sourceLineNumbers, sourcePath, e.ToString()));
186
- return null;
187
- }
109
+ return null;
110
}
111
190
- return this.Section.AddSymbol(new WixBundleHarvestedBundlePackageSymbol(this.PackagePayload.SourceLineNumbers, this.PackagePayload.Id)
191
- {
192
- Win64 = win64,
193
- BundleId = bundleId,
194
- EngineVersion = engineVersion,
195
- ManifestNamespace = manifestNamespace,
196
- ProtocolVersion = protocolVersion,
197
- PerMachine = perMachine,
198
- Version = version,
199
- DisplayName = displayName,
200
- InstallSize = installSize,
201
- });
202
- }
203
-
204
- private int ProcessProtocolVersion(BurnReader burnReader, XmlDocument document)
205
- {
206
- var protocolVersionValue = document.DocumentElement.GetAttribute("ProtocolVersion");
112
+ this.Section.AddSymbol(command.HarvestedBundlePackage);
113
+ this.Section.AddSymbol(command.HarvestedDependencyProvider);
114
208
- if (Int32.TryParse(protocolVersionValue, out var protocolVersion))
115
+ foreach (var relatedBundle in command.RelatedBundles)
116
{
210
- return protocolVersion;
117
+ this.Section.AddSymbol(relatedBundle);
118
}
119
213
- // Assume that the .wixburn section version will change when the Burn protocol changes.
214
- // This should be a safe assumption since only old bundles should be missing the ProtocolVersion from the manifest.
215
- return burnReader.Version == 2 ? 1 : 0;
216
- }
217
-
218
- private bool ProcessWin64(BurnReader burnReader, XmlDocument document, SourceLineNumber sourceLineNumbers, string sourcePath)
219
- {
220
- var win64Value = document.DocumentElement.GetAttribute("Win64");
221
-
222
- switch (win64Value)
223
- {
224
- case "yes":
225
- return true;
226
- case "no":
227
- return false;
228
- }
229
-
230
- switch (burnReader.MachineType)
231
- {
232
- case BurnCommon.IMAGE_FILE_MACHINE_ARM:
233
- case BurnCommon.IMAGE_FILE_MACHINE_ARMNT:
234
- case BurnCommon.IMAGE_FILE_MACHINE_I386:
235
- case BurnCommon.IMAGE_FILE_MACHINE_LOONGARCH32:
236
- return false;
237
- case BurnCommon.IMAGE_FILE_MACHINE_AMD64:
238
- case BurnCommon.IMAGE_FILE_MACHINE_ARM64:
239
- case BurnCommon.IMAGE_FILE_MACHINE_IA64:
240
- case BurnCommon.IMAGE_FILE_MACHINE_LOONGARCH64:
241
- return true;
242
- case BurnCommon.IMAGE_FILE_MACHINE_AM33:
243
- case BurnCommon.IMAGE_FILE_MACHINE_EBC:
244
- case BurnCommon.IMAGE_FILE_MACHINE_M32R:
245
- case BurnCommon.IMAGE_FILE_MACHINE_MIPS16:
246
- case BurnCommon.IMAGE_FILE_MACHINE_MIPSFPU:
247
- case BurnCommon.IMAGE_FILE_MACHINE_MIPSFPU16:
248
- case BurnCommon.IMAGE_FILE_MACHINE_POWERPC:
249
- case BurnCommon.IMAGE_FILE_MACHINE_POWERPCFP:
250
- case BurnCommon.IMAGE_FILE_MACHINE_R4000:
251
- case BurnCommon.IMAGE_FILE_MACHINE_RISCV32:
252
- case BurnCommon.IMAGE_FILE_MACHINE_RISCV64:
253
- case BurnCommon.IMAGE_FILE_MACHINE_RISCV128:
254
- case BurnCommon.IMAGE_FILE_MACHINE_SH3:
255
- case BurnCommon.IMAGE_FILE_MACHINE_SH3DSP:
256
- case BurnCommon.IMAGE_FILE_MACHINE_SH4:
257
- case BurnCommon.IMAGE_FILE_MACHINE_SH5:
258
- case BurnCommon.IMAGE_FILE_MACHINE_THUMB:
259
- case BurnCommon.IMAGE_FILE_MACHINE_WCEMIPSV2:
260
- default:
261
- this.Messaging.Write(BurnBackendWarnings.UnknownCoffMachineType(sourceLineNumbers, sourcePath, burnReader.MachineType));
262
- return false;
263
- }
264
- }
265
-
266
- private long ProcessPackages(XmlDocument document, XmlNamespaceManager namespaceManager)
267
- {
268
- long packageInstallSize = 0;
269
-
270
- foreach (XmlElement packageElement in document.SelectNodes("/burn:BurnManifest/burn:Chain/*", namespaceManager))
271
- {
272
- if (!packageElement.Name.EndsWith("Package"))
273
- {
274
- continue;
275
- }
276
-
277
- if (Int64.TryParse(packageElement.GetAttribute("InstallSize"), out var installSize))
278
- {
279
- packageInstallSize += installSize;
280
- }
281
- }
282
-
283
- return packageInstallSize;
284
- }
285
-
286
- private void ProcessRelatedBundles(XmlDocument document, XmlNamespaceManager namespaceManager, string sourcePath)
287
- {
288
- var sourceLineNumbers = this.PackagePayload.SourceLineNumbers;
289
-
290
- foreach (XmlElement relatedBundleElement in document.SelectNodes("/burn:BurnManifest/burn:RelatedBundle", namespaceManager))
291
- {
292
- var id = relatedBundleElement.GetAttribute("Id");
293
- var actionValue = relatedBundleElement.GetAttribute("Action");
294
-
295
- if (!Enum.TryParse(actionValue, out RelatedBundleActionType action))
296
- {
297
- this.Messaging.Write(BurnBackendWarnings.UnknownBundleRelationAction(sourceLineNumbers, sourcePath, actionValue));
298
- continue;
299
- }
300
-
301
- this.Section.AddSymbol(new WixBundlePackageRelatedBundleSymbol(sourceLineNumbers)
302
- {
303
- PackagePayloadRef = this.PackagePayload.Id.Id,
304
- BundleId = id,
305
- Action = action,
306
- });
307
- }
120
+ return command.HarvestedBundlePackage;
121
}
122
}
123
}
src/wix/WixToolset.Core.Burn/CommandLine/RemotePayloadSubcommand.cs
+78
-1
@@ -9,6 +9,7 @@ namespace WixToolset.Core.Burn.CommandLine
9
using System.Threading;
10
using System.Threading.Tasks;
11
using System.Xml.Linq;
12
+ using WixToolset.Core.Burn.Bundles;
13
using WixToolset.Core.Burn.Interfaces;
14
using WixToolset.Core.Native;
15
using WixToolset.Data;
@@ -17,16 +18,22 @@ namespace WixToolset.Core.Burn.CommandLine
18
19
internal class RemotePayloadSubcommand : BurnSubcommandBase
20
{
21
+ private static readonly XName BundlePackagePayloadName = "BundlePackagePayload";
22
private static readonly XName ExePackagePayloadName = "ExePackagePayload";
23
private static readonly XName MsuPackagePayloadName = "MsuPackagePayload";
24
private static readonly XName PayloadName = "Payload";
25
+ private static readonly XName RemoteBundleName = "RemoteBundle";
26
+ private static readonly XName RemoteRelatedBundleName = "RemoteRelatedBundle";
27
28
public RemotePayloadSubcommand(IServiceProvider serviceProvider)
29
{
30
+ this.ServiceProvider = serviceProvider;
31
this.Messaging = serviceProvider.GetService<IMessaging>();
32
this.PayloadHarvester = serviceProvider.GetService<IPayloadHarvester>();
33
}
34
35
+ private IServiceProvider ServiceProvider { get; }
36
+
37
private IMessaging Messaging { get; }
38
39
private IPayloadHarvester PayloadHarvester { get; }
@@ -37,6 +44,8 @@ namespace WixToolset.Core.Burn.CommandLine
44
45
private List<string> InputPaths { get; } = new List<string>();
46
47
+ private string IntermediateFolder { get; set; }
48
+
49
private string OutputPath { get; set; }
50
51
private WixBundlePackageType? PackageType { get; set; }
@@ -58,6 +67,11 @@ namespace WixToolset.Core.Burn.CommandLine
67
this.BasePaths.Sort();
68
this.BasePaths.Reverse();
69
70
+ if (String.IsNullOrEmpty(this.IntermediateFolder))
71
+ {
72
+ this.IntermediateFolder = Path.GetTempPath();
73
+ }
74
+
75
var elements = this.HarvestRemotePayloads(inputPaths);
76
77
if (!this.Messaging.EncounteredError)
@@ -98,6 +112,10 @@ namespace WixToolset.Core.Burn.CommandLine
112
this.DownloadUrl = parser.GetNextArgumentOrError(argument);
113
return true;
114
115
+ case "intermediatefolder":
116
+ this.IntermediateFolder = parser.GetNextArgumentAsDirectoryOrError(argument);
117
+ return true;
118
+
119
case "packagetype":
120
var packageTypeValue = parser.GetNextArgumentOrError(argument);
121
if (Enum.TryParse<WixBundlePackageType>(packageTypeValue, ignoreCase: true, out var packageType))
@@ -174,7 +192,7 @@ namespace WixToolset.Core.Burn.CommandLine
192
continue;
193
}
194
177
- var payloadSymbol = new WixBundlePayloadSymbol
195
+ var payloadSymbol = new WixBundlePayloadSymbol(null, new Identifier(AccessModifier.Section, "id"))
196
{
197
SourceFile = new IntermediateFieldPathValue { Path = path },
198
};
@@ -225,6 +243,62 @@ namespace WixToolset.Core.Burn.CommandLine
243
element.Add(new XAttribute("Version", payloadSymbol.Version));
244
}
245
246
+ if (element.Name == BundlePackagePayloadName)
247
+ {
248
+ var command = new HarvestBundlePackageCommand(this.ServiceProvider, this.IntermediateFolder, payloadSymbol);
249
+ command.Execute();
250
+
251
+ if (!this.Messaging.EncounteredError)
252
+ {
253
+ var bundleElement = new XElement(RemoteBundleName);
254
+
255
+ bundleElement.Add(new XAttribute("BundleId", command.HarvestedBundlePackage.BundleId));
256
+
257
+ if (!String.IsNullOrEmpty(command.HarvestedBundlePackage.DisplayName))
258
+ {
259
+ bundleElement.Add(new XAttribute("DisplayName", command.HarvestedBundlePackage.DisplayName));
260
+ }
261
+
262
+ if (!String.IsNullOrEmpty(command.HarvestedBundlePackage.EngineVersion))
263
+ {
264
+ bundleElement.Add(new XAttribute("EngineVersion", command.HarvestedBundlePackage.EngineVersion));
265
+ }
266
+
267
+ bundleElement.Add(new XAttribute("InstallSize", command.HarvestedBundlePackage.InstallSize));
268
+ bundleElement.Add(new XAttribute("ManifestNamespace", command.HarvestedBundlePackage.ManifestNamespace));
269
+ bundleElement.Add(new XAttribute("PerMachine", command.HarvestedBundlePackage.PerMachine ? "yes" : "no"));
270
+ bundleElement.Add(new XAttribute("ProviderKey", command.HarvestedDependencyProvider.ProviderKey));
271
+ bundleElement.Add(new XAttribute("ProtocolVersion", command.HarvestedBundlePackage.ProtocolVersion));
272
+
273
+ if (!String.IsNullOrEmpty(command.HarvestedBundlePackage.Version))
274
+ {
275
+ bundleElement.Add(new XAttribute("Version", command.HarvestedBundlePackage.Version));
276
+ }
277
+
278
+ bundleElement.Add(new XAttribute("Win64", command.HarvestedBundlePackage.Win64 ? "yes" : "no"));
279
+
280
+ var setUpgradeCode = false;
281
+ foreach (var relatedBundle in command.RelatedBundles)
282
+ {
283
+ if (!setUpgradeCode && relatedBundle.Action == RelatedBundleActionType.Upgrade)
284
+ {
285
+ setUpgradeCode = true;
286
+ bundleElement.Add(new XAttribute("UpgradeCode", relatedBundle.BundleId));
287
+ continue;
288
+ }
289
+
290
+ var relatedBundleElement = new XElement(RemoteRelatedBundleName);
291
+
292
+ relatedBundleElement.Add(new XAttribute("Id", relatedBundle.BundleId));
293
+ relatedBundleElement.Add(new XAttribute("Action", relatedBundle.Action.ToString()));
294
+
295
+ bundleElement.Add(relatedBundleElement);
296
+ }
297
+
298
+ element.Add(bundleElement);
299
+ }
300
+ }
301
+
302
yield return element;
303
}
304
}
@@ -237,6 +311,9 @@ namespace WixToolset.Core.Burn.CommandLine
311
312
switch (extension.ToUpperInvariant())
313
{
314
+ case "BUNDLE":
315
+ return new XElement(BundlePackagePayloadName);
316
+
317
case "EXE":
318
case ".EXE":
319
return new XElement(ExePackagePayloadName);
src/wix/test/WixToolsetTest.CoreIntegration/BundleFixture.cs
+1
-1
@@ -574,7 +574,7 @@ namespace WixToolsetTest.CoreIntegration
574
}
575
576
[Fact]
577
- public void CantBuildWithSubfolderContainer()
577
+ public void CanBuildWithSubfolderContainer()
578
{
579
var folder = TestData.Get(@"TestData");
580
src/wix/test/WixToolsetTest.CoreIntegration/PackagePayloadFixture.cs
+2
-2
@@ -90,7 +90,7 @@ namespace WixToolsetTest.CoreIntegration
90
}
91
92
[Fact]
93
- public void CanSpecifyPackagePayloadInPayloadGroup()
93
+ public void CanSpecifyExePackagePayloadInPayloadGroup()
94
{
95
var folder = TestData.Get(@"TestData");
96
@@ -135,7 +135,7 @@ namespace WixToolsetTest.CoreIntegration
135
}
136
137
[Fact]
138
- public void CanSpecifyPackagePayloadWithCertificate()
138
+ public void CanSpecifyExePackagePayloadWithCertificate()
139
{
140
var folder = TestData.Get(@"TestData", "PackagePayload");
141
src/wix/test/WixToolsetTest.CoreIntegration/RemotePayloadFixture.cs
+34
-1
@@ -11,7 +11,40 @@ namespace WixToolsetTest.CoreIntegration
11
public class RemotePayloadFixture
12
{
13
[Fact]
14
- public void CanGetRemotePayload()
14
+ public void CanGetRemoteV3BundlePayload()
15
+ {
16
+ var folder = TestData.Get(@"TestData");
17
+
18
+ using (var fs = new DisposableFileSystem())
19
+ {
20
+ var outputFolder = fs.GetFolder();
21
+ var outFile = Path.Combine(outputFolder, "out.xml");
22
+
23
+ var result = WixRunner.Execute(new[]
24
+ {
25
+ "burn", "remotepayload",
26
+ Path.Combine(folder, ".Data", "v3bundle.exe"),
27
+ "-downloadurl", "https://www.example.com/files/{0}",
28
+ "-o", outFile,
29
+ "-packagetype", "bundle",
30
+ });
31
+
32
+ result.AssertSuccess();
33
+
34
+ var elements = File.ReadAllLines(outFile);
35
+ elements = elements.Select(s => s.Replace("\"", "'")).ToArray();
36
+
37
+ WixAssert.CompareLineByLine(new[]
38
+ {
39
+ "<BundlePackagePayload Name='v3bundle.exe' ProductName='CustomV3Theme' Description='CustomV3Theme' DownloadUrl='https://www.example.com/files/v3bundle.exe' Hash='80739E7B8C31D75B4CDC48D60D74F5E481CB904212A3AE3FB0920365A163FBF32B0C5C175AB516D4124F107923E96200605DE1D560D362FEB47350FA727823B4' Size='648397' Version='1.0.0.0'>",
40
+ " <RemoteBundle BundleId='{215A70DB-AB35-48C7-BE51-D66EAAC87177}' DisplayName='CustomV3Theme' InstallSize='1135' ManifestNamespace='http://schemas.microsoft.com/wix/2008/Burn' PerMachine='yes' ProviderKey='{215a70db-ab35-48c7-be51-d66eaac87177}' ProtocolVersion='1' Version='1.0.0.0' Win64='no' UpgradeCode='{2BF4C01F-C132-4E70-97AB-2BC68C7CCD10}' />",
41
+ "</BundlePackagePayload>",
42
+ }, elements);
43
+ }
44
+ }
45
+
46
+ [Fact]
47
+ public void CanGetRemoteExePayload()
48
{
49
var folder = TestData.Get(@"TestData");
50