diff options
22 files changed, 814 insertions, 11 deletions
diff --git a/src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs b/src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs index 93620e1b..c9a111c6 100644 --- a/src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs +++ b/src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs | |||
@@ -380,6 +380,13 @@ namespace WixToolset.Core.Burn | |||
380 | // Update the bundle per-machine/per-user scope based on the chained packages. | 380 | // Update the bundle per-machine/per-user scope based on the chained packages. |
381 | this.ResolveBundleInstallScope(section, bundleSymbol, orderedFacades); | 381 | this.ResolveBundleInstallScope(section, bundleSymbol, orderedFacades); |
382 | 382 | ||
383 | var softwareTags = section.Symbols.OfType<WixBundleTagSymbol>().ToList(); | ||
384 | if (softwareTags.Any()) | ||
385 | { | ||
386 | var command = new ProcessBundleSoftwareTagsCommand(section, softwareTags); | ||
387 | command.Execute(); | ||
388 | } | ||
389 | |||
383 | // Give the extension one last hook before generating the output files. | 390 | // Give the extension one last hook before generating the output files. |
384 | foreach (var extension in this.BackendExtensions) | 391 | foreach (var extension in this.BackendExtensions) |
385 | { | 392 | { |
diff --git a/src/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs b/src/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs index c51d380c..36ced6cf 100644 --- a/src/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs +++ b/src/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs | |||
@@ -82,6 +82,7 @@ namespace WixToolset.Core.Burn.Bind | |||
82 | case SymbolDefinitionType.WixBundleRelatedPackage: | 82 | case SymbolDefinitionType.WixBundleRelatedPackage: |
83 | case SymbolDefinitionType.WixBundleRollbackBoundary: | 83 | case SymbolDefinitionType.WixBundleRollbackBoundary: |
84 | case SymbolDefinitionType.WixBundleSlipstreamMsp: | 84 | case SymbolDefinitionType.WixBundleSlipstreamMsp: |
85 | case SymbolDefinitionType.WixBundleTag: | ||
85 | case SymbolDefinitionType.WixBundleUpdate: | 86 | case SymbolDefinitionType.WixBundleUpdate: |
86 | case SymbolDefinitionType.WixBundleVariable: | 87 | case SymbolDefinitionType.WixBundleVariable: |
87 | case SymbolDefinitionType.WixBuildInfo: | 88 | case SymbolDefinitionType.WixBuildInfo: |
diff --git a/src/WixToolset.Core.Burn/Bind/ProcessBundleSoftwareTagsCommand.cs b/src/WixToolset.Core.Burn/Bind/ProcessBundleSoftwareTagsCommand.cs new file mode 100644 index 00000000..8584d2a4 --- /dev/null +++ b/src/WixToolset.Core.Burn/Bind/ProcessBundleSoftwareTagsCommand.cs | |||
@@ -0,0 +1,142 @@ | |||
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.Bind | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections.Generic; | ||
7 | using System.IO; | ||
8 | using System.Linq; | ||
9 | using System.Text; | ||
10 | using System.Xml; | ||
11 | using WixToolset.Data; | ||
12 | using WixToolset.Data.Symbols; | ||
13 | using WixToolset.Dtf.WindowsInstaller; | ||
14 | |||
15 | internal class ProcessBundleSoftwareTagsCommand | ||
16 | { | ||
17 | public ProcessBundleSoftwareTagsCommand(IntermediateSection section, IEnumerable<WixBundleTagSymbol> softwareTags) | ||
18 | { | ||
19 | this.Section = section; | ||
20 | this.SoftwareTags = softwareTags; | ||
21 | } | ||
22 | |||
23 | private IntermediateSection Section { get; } | ||
24 | |||
25 | private IEnumerable<WixBundleTagSymbol> SoftwareTags { get; } | ||
26 | |||
27 | public void Execute() | ||
28 | { | ||
29 | var bundleInfo = this.Section.Symbols.OfType<WixBundleSymbol>().FirstOrDefault(); | ||
30 | var bundleId = NormalizeGuid(bundleInfo.BundleId); | ||
31 | var upgradeCode = NormalizeGuid(bundleInfo.UpgradeCode); | ||
32 | |||
33 | var uniqueId = String.Concat("wix:bundle/", bundleId); | ||
34 | var persistentId = String.Concat("wix:bundle.upgrade/", upgradeCode); | ||
35 | |||
36 | // Try to collect all the software id tags from all the child packages. | ||
37 | var containedTags = CollectPackageTags(this.Section); | ||
38 | |||
39 | foreach (var bundleTag in this.SoftwareTags) | ||
40 | { | ||
41 | using (var ms = new MemoryStream()) | ||
42 | { | ||
43 | CreateTagFile(ms, uniqueId, bundleInfo.Name, bundleInfo.Version, bundleTag.Regid, bundleInfo.Manufacturer, persistentId, containedTags); | ||
44 | bundleTag.Xml = Encoding.UTF8.GetString(ms.ToArray()); | ||
45 | } | ||
46 | } | ||
47 | } | ||
48 | |||
49 | private static string NormalizeGuid(string guidString) | ||
50 | { | ||
51 | if (Guid.TryParse(guidString, out var guid)) | ||
52 | { | ||
53 | return guid.ToString("D").ToUpperInvariant(); | ||
54 | } | ||
55 | |||
56 | return guidString; | ||
57 | } | ||
58 | |||
59 | private static IEnumerable<SoftwareTag> CollectPackageTags(IntermediateSection section) | ||
60 | { | ||
61 | var tags = new List<SoftwareTag>(); | ||
62 | |||
63 | var msiPackages = section.Symbols.OfType<WixBundlePackageSymbol>().Where(s => s.Type == WixBundlePackageType.Msi).ToList(); | ||
64 | if (msiPackages.Any()) | ||
65 | { | ||
66 | var payloadSymbolsById = section.Symbols.OfType<WixBundlePayloadSymbol>().ToDictionary(s => s.Id.Id); | ||
67 | |||
68 | foreach (var msiPackage in msiPackages) | ||
69 | { | ||
70 | var payload = payloadSymbolsById[msiPackage.PayloadRef]; | ||
71 | |||
72 | using (var db = new Database(payload.SourceFile.Path)) | ||
73 | { | ||
74 | using (var view = db.OpenView("SELECT `Regid`, `TagId` FROM `SoftwareIdentificationTag`")) | ||
75 | { | ||
76 | view.Execute(); | ||
77 | while (true) | ||
78 | { | ||
79 | using (var record = view.Fetch()) | ||
80 | { | ||
81 | if (null == record) | ||
82 | { | ||
83 | break; | ||
84 | } | ||
85 | |||
86 | tags.Add(new SoftwareTag { Regid = record.GetString(1), Id = record.GetString(2) }); | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | } | ||
93 | |||
94 | return tags; | ||
95 | } | ||
96 | |||
97 | private static void CreateTagFile(Stream stream, string uniqueId, string name, string version, string regid, string manufacturer, string persistendId, IEnumerable<SoftwareTag> containedTags) | ||
98 | { | ||
99 | var versionScheme = Version.TryParse(version, out _) ? "multipartnumeric" : "alphanumeric"; | ||
100 | |||
101 | using (var writer = XmlWriter.Create(stream, new XmlWriterSettings { Indent = true})) | ||
102 | { | ||
103 | writer.WriteStartDocument(); | ||
104 | writer.WriteStartElement("SoftwareIdentity", "http://standards.iso.org/iso/19770/-2/2015/schema.xsd"); | ||
105 | writer.WriteAttributeString("tagId", uniqueId); | ||
106 | writer.WriteAttributeString("name", name); | ||
107 | writer.WriteAttributeString("version", version); | ||
108 | writer.WriteAttributeString("versionScheme", versionScheme); | ||
109 | |||
110 | writer.WriteStartElement("Entity"); | ||
111 | writer.WriteAttributeString("name", manufacturer); | ||
112 | writer.WriteAttributeString("regid", regid); | ||
113 | writer.WriteAttributeString("role", "softwareCreator tagCreator"); | ||
114 | writer.WriteEndElement(); // </Entity> | ||
115 | |||
116 | if (!String.IsNullOrEmpty(persistendId)) | ||
117 | { | ||
118 | writer.WriteStartElement("Meta"); | ||
119 | writer.WriteAttributeString("persistentId", persistendId); | ||
120 | writer.WriteEndElement(); // </Meta> | ||
121 | } | ||
122 | |||
123 | foreach (var containedTag in containedTags) | ||
124 | { | ||
125 | writer.WriteStartElement("Link"); | ||
126 | writer.WriteAttributeString("rel", "component"); | ||
127 | writer.WriteAttributeString("href", String.Concat("swid:", containedTag.Id)); | ||
128 | writer.WriteEndElement(); // </Link> | ||
129 | } | ||
130 | |||
131 | writer.WriteEndElement(); // </SoftwareIdentity> | ||
132 | } | ||
133 | } | ||
134 | |||
135 | private class SoftwareTag | ||
136 | { | ||
137 | public string Regid { get; set; } | ||
138 | |||
139 | public string Id { get; set; } | ||
140 | } | ||
141 | } | ||
142 | } | ||
diff --git a/src/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs b/src/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs index 71bc0229..3bc6bf1b 100644 --- a/src/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs +++ b/src/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs | |||
@@ -295,17 +295,15 @@ namespace WixToolset.Core.Burn.Bundles | |||
295 | writer.WriteEndElement(); // </Update> | 295 | writer.WriteEndElement(); // </Update> |
296 | } | 296 | } |
297 | 297 | ||
298 | #if TODO // Handle SWID Tags | 298 | foreach (var bundleTagSymbol in this.Section.Symbols.OfType<WixBundleTagSymbol>()) |
299 | var bundleTags = this.Output.Tables["WixBundleTag"].RowsAs<Row>(); | ||
300 | foreach (var row in bundleTags) | ||
301 | { | 299 | { |
302 | writer.WriteStartElement("SoftwareTag"); | 300 | writer.WriteStartElement("SoftwareTag"); |
303 | writer.WriteAttributeString("Filename", (string)row[0]); | 301 | writer.WriteAttributeString("Filename", bundleTagSymbol.Filename); |
304 | writer.WriteAttributeString("Regid", (string)row[1]); | 302 | writer.WriteAttributeString("Regid", bundleTagSymbol.Regid); |
305 | writer.WriteCData((string)row[4]); | 303 | writer.WriteAttributeString("Path", bundleTagSymbol.InstallPath); |
304 | writer.WriteCData(bundleTagSymbol.Xml); | ||
306 | writer.WriteEndElement(); | 305 | writer.WriteEndElement(); |
307 | } | 306 | } |
308 | #endif | ||
309 | 307 | ||
310 | writer.WriteEndElement(); // </Register> | 308 | writer.WriteEndElement(); // </Register> |
311 | 309 | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs index 012c7c4c..25a093fd 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs | |||
@@ -282,6 +282,18 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
282 | return null; | 282 | return null; |
283 | } | 283 | } |
284 | 284 | ||
285 | // Process SoftwareTags in MSI packages. | ||
286 | if (SectionType.Product == section.Type) | ||
287 | { | ||
288 | var softwareTags = section.Symbols.OfType<WixProductTagSymbol>().ToList(); | ||
289 | |||
290 | if (softwareTags.Any()) | ||
291 | { | ||
292 | var command = new ProcessPackageSoftwareTagsCommand(section, softwareTags, this.IntermediateFolder); | ||
293 | command.Execute(); | ||
294 | } | ||
295 | } | ||
296 | |||
285 | // Gather information about files that do not come from merge modules. | 297 | // Gather information about files that do not come from merge modules. |
286 | { | 298 | { |
287 | var command = new UpdateFileFacadesCommand(this.Messaging, section, fileFacades, fileFacades.Where(f => !f.FromModule), variableCache, overwriteHash: true); | 299 | var command = new UpdateFileFacadesCommand(this.Messaging, section, fileFacades, fileFacades.Where(f => !f.FromModule), variableCache, overwriteHash: true); |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs index b52ff434..37383caa 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs | |||
@@ -231,6 +231,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
231 | case SymbolDefinitionType.WixPatchRef: | 231 | case SymbolDefinitionType.WixPatchRef: |
232 | case SymbolDefinitionType.WixPatchTarget: | 232 | case SymbolDefinitionType.WixPatchTarget: |
233 | case SymbolDefinitionType.WixProperty: | 233 | case SymbolDefinitionType.WixProperty: |
234 | case SymbolDefinitionType.WixProductTag: | ||
234 | case SymbolDefinitionType.WixSimpleReference: | 235 | case SymbolDefinitionType.WixSimpleReference: |
235 | case SymbolDefinitionType.WixSuppressAction: | 236 | case SymbolDefinitionType.WixSuppressAction: |
236 | case SymbolDefinitionType.WixSuppressModularization: | 237 | case SymbolDefinitionType.WixSuppressModularization: |
@@ -456,7 +457,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
456 | 457 | ||
457 | private void AddDirectorySymbol(DirectorySymbol symbol) | 458 | private void AddDirectorySymbol(DirectorySymbol symbol) |
458 | { | 459 | { |
459 | if (String.IsNullOrEmpty(symbol.ShortName) && !symbol.Name.Equals(".") && !symbol.Name.Equals("SourceDir") && !Common.IsValidShortFilename(symbol.Name, false)) | 460 | if (String.IsNullOrEmpty(symbol.ShortName) && symbol.Name != null && !symbol.Name.Equals(".") && !symbol.Name.Equals("SourceDir") && !Common.IsValidShortFilename(symbol.Name, false)) |
460 | { | 461 | { |
461 | symbol.ShortName = CreateShortName(symbol.Name, false, false, "Directory", symbol.ParentDirectoryRef); | 462 | symbol.ShortName = CreateShortName(symbol.Name, false, false, "Directory", symbol.ParentDirectoryRef); |
462 | } | 463 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessPackageSoftwareTagsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessPackageSoftwareTagsCommand.cs new file mode 100644 index 00000000..9a068603 --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessPackageSoftwareTagsCommand.cs | |||
@@ -0,0 +1,131 @@ | |||
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.WindowsInstaller.Bind | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections.Generic; | ||
7 | using System.IO; | ||
8 | using System.Linq; | ||
9 | using System.Xml; | ||
10 | using WixToolset.Data; | ||
11 | using WixToolset.Data.Symbols; | ||
12 | |||
13 | internal class ProcessPackageSoftwareTagsCommand | ||
14 | { | ||
15 | public ProcessPackageSoftwareTagsCommand(IntermediateSection section, IEnumerable<WixProductTagSymbol> softwareTags, string intermediateFolder) | ||
16 | { | ||
17 | this.Section = section; | ||
18 | this.SoftwareTags = softwareTags; | ||
19 | this.IntermediateFolder = intermediateFolder; | ||
20 | } | ||
21 | |||
22 | private string IntermediateFolder { get; } | ||
23 | |||
24 | private IntermediateSection Section { get; } | ||
25 | |||
26 | private IEnumerable<WixProductTagSymbol> SoftwareTags { get; } | ||
27 | |||
28 | public void Execute() | ||
29 | { | ||
30 | string productName = null; | ||
31 | string productVersion = null; | ||
32 | string manufacturer = null; | ||
33 | string upgradeCode = null; | ||
34 | |||
35 | var summaryInfo = this.Section.Symbols.OfType<SummaryInformationSymbol>().FirstOrDefault(s => s.PropertyId == SummaryInformationType.PackageCode); | ||
36 | var packageCode = NormalizeGuid(summaryInfo?.Value); | ||
37 | |||
38 | foreach (var property in this.Section.Symbols.OfType<PropertySymbol>()) | ||
39 | { | ||
40 | switch (property.Id.Id) | ||
41 | { | ||
42 | case "ProductName": | ||
43 | productName = property.Value; | ||
44 | break; | ||
45 | case "ProductVersion": | ||
46 | productVersion = property.Value; | ||
47 | break; | ||
48 | case "Manufacturer": | ||
49 | manufacturer = property.Value; | ||
50 | break; | ||
51 | case "UpgradeCode": | ||
52 | upgradeCode = NormalizeGuid(property.Value); | ||
53 | break; | ||
54 | } | ||
55 | } | ||
56 | |||
57 | var fileSymbolsById = this.Section.Symbols.OfType<FileSymbol>().Where(f => f.Id != null).ToDictionary(f => f.Id.Id); | ||
58 | |||
59 | var workingFolder = Path.Combine(this.IntermediateFolder, "_swidtag"); | ||
60 | |||
61 | Directory.CreateDirectory(workingFolder); | ||
62 | |||
63 | foreach (var tagRow in this.SoftwareTags) | ||
64 | { | ||
65 | if (fileSymbolsById.TryGetValue(tagRow.FileRef, out var fileSymbol)) | ||
66 | { | ||
67 | var uniqueId = String.Concat("msi:package/", packageCode); | ||
68 | var persistentId = String.IsNullOrEmpty(upgradeCode) ? null : String.Concat("msi:upgrade/", upgradeCode); | ||
69 | |||
70 | // Write the tag file. | ||
71 | fileSymbol.Source = new IntermediateFieldPathValue { Path = Path.Combine(workingFolder, fileSymbol.Name) }; | ||
72 | |||
73 | using (var fs = new FileStream(fileSymbol.Source.Path, FileMode.Create)) | ||
74 | { | ||
75 | CreateTagFile(fs, uniqueId, productName, productVersion, tagRow.Regid, manufacturer, persistentId); | ||
76 | } | ||
77 | |||
78 | // Ensure the matching "SoftwareIdentificationTag" row exists and | ||
79 | // is populated correctly. | ||
80 | this.Section.AddSymbol(new SoftwareIdentificationTagSymbol(tagRow.SourceLineNumbers, tagRow.Id) | ||
81 | { | ||
82 | FileRef = fileSymbol.Id.Id, | ||
83 | Regid = tagRow.Regid, | ||
84 | TagId = uniqueId, | ||
85 | PersistentId = persistentId | ||
86 | }); | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | |||
91 | private static string NormalizeGuid(string guidString) | ||
92 | { | ||
93 | if (Guid.TryParse(guidString, out var guid)) | ||
94 | { | ||
95 | return guid.ToString("D").ToUpperInvariant(); | ||
96 | } | ||
97 | |||
98 | return guidString; | ||
99 | } | ||
100 | |||
101 | private static void CreateTagFile(Stream stream, string uniqueId, string name, string version, string regid, string manufacturer, string persistendId) | ||
102 | { | ||
103 | var versionScheme = Version.TryParse(version, out _) ? "multipartnumeric" : "alphanumeric"; | ||
104 | |||
105 | using (var writer = XmlWriter.Create(stream, new XmlWriterSettings { Indent = true })) | ||
106 | { | ||
107 | writer.WriteStartDocument(); | ||
108 | writer.WriteStartElement("SoftwareIdentity", "http://standards.iso.org/iso/19770/-2/2015/schema.xsd"); | ||
109 | writer.WriteAttributeString("tagId", uniqueId); | ||
110 | writer.WriteAttributeString("name", name); | ||
111 | writer.WriteAttributeString("version", version); | ||
112 | writer.WriteAttributeString("versionScheme", versionScheme); | ||
113 | |||
114 | writer.WriteStartElement("Entity"); | ||
115 | writer.WriteAttributeString("name", manufacturer); | ||
116 | writer.WriteAttributeString("regid", regid); | ||
117 | writer.WriteAttributeString("role", "softwareCreator tagCreator"); | ||
118 | writer.WriteEndElement(); // </Entity> | ||
119 | |||
120 | if (!String.IsNullOrEmpty(persistendId)) | ||
121 | { | ||
122 | writer.WriteStartElement("Meta"); | ||
123 | writer.WriteAttributeString("persistentId", persistendId); | ||
124 | writer.WriteEndElement(); // </Meta> | ||
125 | } | ||
126 | |||
127 | writer.WriteEndElement(); // </SoftwareIdentity> | ||
128 | } | ||
129 | } | ||
130 | } | ||
131 | } | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs index 938627ed..d5bdc797 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs | |||
@@ -45,7 +45,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
45 | { | 45 | { |
46 | var assemblyNameSymbols = this.Section.Symbols.OfType<MsiAssemblyNameSymbol>().ToDictionary(t => t.Id.Id); | 46 | var assemblyNameSymbols = this.Section.Symbols.OfType<MsiAssemblyNameSymbol>().ToDictionary(t => t.Id.Id); |
47 | 47 | ||
48 | foreach (var file in this.UpdateFileFacades) | 48 | foreach (var file in this.UpdateFileFacades.Where(f => f.SourcePath != null)) |
49 | { | 49 | { |
50 | this.UpdateFileFacade(file, assemblyNameSymbols); | 50 | this.UpdateFileFacade(file, assemblyNameSymbols); |
51 | } | 51 | } |
diff --git a/src/WixToolset.Core/Bind/FileFacade.cs b/src/WixToolset.Core/Bind/FileFacade.cs index ec4e9725..9705cd01 100644 --- a/src/WixToolset.Core/Bind/FileFacade.cs +++ b/src/WixToolset.Core/Bind/FileFacade.cs | |||
@@ -125,7 +125,7 @@ namespace WixToolset.Core.Bind | |||
125 | 125 | ||
126 | public SourceLineNumber SourceLineNumber => this.FileRow == null ? this.FileSymbol.SourceLineNumbers : this.FileRow.SourceLineNumbers; | 126 | public SourceLineNumber SourceLineNumber => this.FileRow == null ? this.FileSymbol.SourceLineNumbers : this.FileRow.SourceLineNumbers; |
127 | 127 | ||
128 | public string SourcePath => this.FileRow == null ? this.FileSymbol.Source.Path : this.FileRow.Source; | 128 | public string SourcePath => this.FileRow == null ? this.FileSymbol.Source?.Path : this.FileRow.Source; |
129 | 129 | ||
130 | public bool Compressed => this.FileRow == null ? (this.FileSymbol.Attributes & FileSymbolAttributes.Compressed) == FileSymbolAttributes.Compressed : (this.FileRow.Attributes & WindowsInstallerConstants.MsidbFileAttributesCompressed) == WindowsInstallerConstants.MsidbFileAttributesCompressed; | 130 | public bool Compressed => this.FileRow == null ? (this.FileSymbol.Attributes & FileSymbolAttributes.Compressed) == FileSymbolAttributes.Compressed : (this.FileRow.Attributes & WindowsInstallerConstants.MsidbFileAttributesCompressed) == WindowsInstallerConstants.MsidbFileAttributesCompressed; |
131 | 131 | ||
diff --git a/src/WixToolset.Core/CompilerCore.cs b/src/WixToolset.Core/CompilerCore.cs index 1f6d6329..53e0f3fc 100644 --- a/src/WixToolset.Core/CompilerCore.cs +++ b/src/WixToolset.Core/CompilerCore.cs | |||
@@ -6,7 +6,6 @@ namespace WixToolset.Core | |||
6 | using System.Collections; | 6 | using System.Collections; |
7 | using System.Collections.Generic; | 7 | using System.Collections.Generic; |
8 | using System.Diagnostics; | 8 | using System.Diagnostics; |
9 | using System.Diagnostics.CodeAnalysis; | ||
10 | using System.Globalization; | 9 | using System.Globalization; |
11 | using System.Reflection; | 10 | using System.Reflection; |
12 | using System.Text; | 11 | using System.Text; |
diff --git a/src/WixToolset.Core/CompilerErrors.cs b/src/WixToolset.Core/CompilerErrors.cs new file mode 100644 index 00000000..da64c376 --- /dev/null +++ b/src/WixToolset.Core/CompilerErrors.cs | |||
@@ -0,0 +1,30 @@ | |||
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 | ||
4 | { | ||
5 | using WixToolset.Data; | ||
6 | |||
7 | internal static class CompilerErrors | ||
8 | { | ||
9 | public static Message IllegalName(SourceLineNumber sourceLineNumbers, string parentElement, string name) | ||
10 | { | ||
11 | return Message(sourceLineNumbers, Ids.IllegalName, "The Tag/@Name attribute value, '{1}', contains invalid filename identifiers. The Tag/@Name may have defaulted from the {0}/@Name attrbute. If so, use the Tag/@Name attribute to provide a valid filename. Any character except for the follow may be used: \\ ? | > < : / * \".", parentElement, name); | ||
12 | } | ||
13 | |||
14 | public static Message ExampleRegid(SourceLineNumber sourceLineNumbers, string regid) | ||
15 | { | ||
16 | return Message(sourceLineNumbers, Ids.ExampleRegid, "Regid '{0}' is a placeholder that must be replaced with an appropriate value for your installation. Use the simplified URI for your organization or project.", regid); | ||
17 | } | ||
18 | |||
19 | private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) | ||
20 | { | ||
21 | return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args); | ||
22 | } | ||
23 | |||
24 | public enum Ids | ||
25 | { | ||
26 | IllegalName = 6601, | ||
27 | ExampleRegid = 6602, | ||
28 | } | ||
29 | } | ||
30 | } | ||
diff --git a/src/WixToolset.Core/Compiler_2.cs b/src/WixToolset.Core/Compiler_2.cs index 09d56e49..295392c8 100644 --- a/src/WixToolset.Core/Compiler_2.cs +++ b/src/WixToolset.Core/Compiler_2.cs | |||
@@ -316,6 +316,9 @@ namespace WixToolset.Core | |||
316 | string parentName = null; | 316 | string parentName = null; |
317 | this.ParseSFPCatalogElement(child, ref parentName); | 317 | this.ParseSFPCatalogElement(child, ref parentName); |
318 | break; | 318 | break; |
319 | case "SoftwareTag": | ||
320 | this.ParsePackageTagElement(child); | ||
321 | break; | ||
319 | case "SummaryInformation": | 322 | case "SummaryInformation": |
320 | this.ParseSummaryInformationElement(child, ref isCodepageSet, ref isPackageNameSet, ref isKeywordsSet, ref isPackageAuthorSet); | 323 | this.ParseSummaryInformationElement(child, ref isCodepageSet, ref isPackageNameSet, ref isKeywordsSet, ref isPackageAuthorSet); |
321 | break; | 324 | break; |
diff --git a/src/WixToolset.Core/Compiler_Bundle.cs b/src/WixToolset.Core/Compiler_Bundle.cs index 7a386de7..1ee09166 100644 --- a/src/WixToolset.Core/Compiler_Bundle.cs +++ b/src/WixToolset.Core/Compiler_Bundle.cs | |||
@@ -346,6 +346,9 @@ namespace WixToolset.Core | |||
346 | case "SetVariableRef": | 346 | case "SetVariableRef": |
347 | this.ParseSimpleRefElement(child, SymbolDefinitions.WixSetVariable); | 347 | this.ParseSimpleRefElement(child, SymbolDefinitions.WixSetVariable); |
348 | break; | 348 | break; |
349 | case "SoftwareTag": | ||
350 | this.ParseBundleTagElement(child); | ||
351 | break; | ||
349 | case "Update": | 352 | case "Update": |
350 | this.ParseUpdateElement(child); | 353 | this.ParseUpdateElement(child); |
351 | break; | 354 | break; |
diff --git a/src/WixToolset.Core/Compiler_Patch.cs b/src/WixToolset.Core/Compiler_Patch.cs index 2fb1affb..83737c43 100644 --- a/src/WixToolset.Core/Compiler_Patch.cs +++ b/src/WixToolset.Core/Compiler_Patch.cs | |||
@@ -410,6 +410,9 @@ namespace WixToolset.Core | |||
410 | case "PropertyRef": | 410 | case "PropertyRef": |
411 | this.ParsePatchChildRefElement(child, "Property"); | 411 | this.ParsePatchChildRefElement(child, "Property"); |
412 | break; | 412 | break; |
413 | case "SoftwareTagRef": | ||
414 | this.ParseTagRefElement(child); | ||
415 | break; | ||
413 | case "UIRef": | 416 | case "UIRef": |
414 | this.ParsePatchChildRefElement(child, "WixUI"); | 417 | this.ParsePatchChildRefElement(child, "WixUI"); |
415 | break; | 418 | break; |
diff --git a/src/WixToolset.Core/Compiler_Tag.cs b/src/WixToolset.Core/Compiler_Tag.cs new file mode 100644 index 00000000..2b3523c8 --- /dev/null +++ b/src/WixToolset.Core/Compiler_Tag.cs | |||
@@ -0,0 +1,315 @@ | |||
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 | ||
4 | { | ||
5 | using System; | ||
6 | using System.Xml.Linq; | ||
7 | using WixToolset.Data; | ||
8 | using WixToolset.Data.Symbols; | ||
9 | |||
10 | /// <summary> | ||
11 | /// Compiler of the WiX toolset. | ||
12 | /// </summary> | ||
13 | internal partial class Compiler : ICompiler | ||
14 | { | ||
15 | /// <summary> | ||
16 | /// Parses a Tag element for Software Id Tag registration under a Bundle element. | ||
17 | /// </summary> | ||
18 | /// <param name="node">The element to parse.</param> | ||
19 | private void ParseBundleTagElement(XElement node) | ||
20 | { | ||
21 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
22 | string name = null; | ||
23 | string regid = null; | ||
24 | string installPath = null; | ||
25 | |||
26 | foreach (var attrib in node.Attributes()) | ||
27 | { | ||
28 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
29 | { | ||
30 | switch (attrib.Name.LocalName) | ||
31 | { | ||
32 | case "Name": | ||
33 | name = this.Core.GetAttributeLongFilename(sourceLineNumbers, attrib, false); | ||
34 | break; | ||
35 | case "Regid": | ||
36 | regid = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
37 | break; | ||
38 | case "InstallDirectory": | ||
39 | case "Bitness": | ||
40 | this.Core.Write(ErrorMessages.ExpectedParentWithAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "Package")); | ||
41 | break; | ||
42 | case "InstallPath": | ||
43 | installPath = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
44 | break; | ||
45 | default: | ||
46 | this.Core.UnexpectedAttribute(node, attrib); | ||
47 | break; | ||
48 | } | ||
49 | } | ||
50 | else | ||
51 | { | ||
52 | this.Core.ParseExtensionAttribute(node, attrib); | ||
53 | } | ||
54 | } | ||
55 | |||
56 | this.Core.ParseForExtensionElements(node); | ||
57 | |||
58 | if (String.IsNullOrEmpty(name)) | ||
59 | { | ||
60 | name = node.Parent?.Attribute("Name")?.Value; | ||
61 | |||
62 | if (String.IsNullOrEmpty(name)) | ||
63 | { | ||
64 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name")); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | if (!String.IsNullOrEmpty(name) && !this.Core.IsValidLongFilename(name)) | ||
69 | { | ||
70 | this.Core.Write(CompilerErrors.IllegalName(sourceLineNumbers, node.Name.LocalName, name)); | ||
71 | } | ||
72 | |||
73 | if (String.IsNullOrEmpty(regid)) | ||
74 | { | ||
75 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Regid")); | ||
76 | } | ||
77 | else if (regid.Equals("example.com", StringComparison.OrdinalIgnoreCase)) | ||
78 | { | ||
79 | this.Core.Write(CompilerErrors.ExampleRegid(sourceLineNumbers, regid)); | ||
80 | } | ||
81 | |||
82 | if (String.IsNullOrEmpty(installPath)) | ||
83 | { | ||
84 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "InstallPath")); | ||
85 | } | ||
86 | |||
87 | if (!this.Core.EncounteredError) | ||
88 | { | ||
89 | this.Core.AddSymbol(new WixBundleTagSymbol(sourceLineNumbers) | ||
90 | { | ||
91 | Filename = String.Concat(name, ".swidtag"), | ||
92 | Regid = regid, | ||
93 | Name = name, | ||
94 | InstallPath = installPath | ||
95 | }); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | /// <summary> | ||
100 | /// Parses a Tag element for Software Id Tag registration under a Package element. | ||
101 | /// </summary> | ||
102 | /// <param name="node">The element to parse.</param> | ||
103 | private void ParsePackageTagElement(XElement node) | ||
104 | { | ||
105 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
106 | Identifier id = null; | ||
107 | string name = null; | ||
108 | string regid = null; | ||
109 | string feature = null; | ||
110 | string installDirectory = null; | ||
111 | var win64 = this.Context.IsCurrentPlatform64Bit; | ||
112 | |||
113 | foreach (var attrib in node.Attributes()) | ||
114 | { | ||
115 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
116 | { | ||
117 | switch (attrib.Name.LocalName) | ||
118 | { | ||
119 | case "Id": | ||
120 | id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); | ||
121 | break; | ||
122 | case "Name": | ||
123 | name = this.Core.GetAttributeLongFilename(sourceLineNumbers, attrib, false); | ||
124 | break; | ||
125 | case "Regid": | ||
126 | regid = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
127 | break; | ||
128 | case "Feature": | ||
129 | feature = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
130 | break; | ||
131 | case "InstallDirectory": | ||
132 | installDirectory = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
133 | break; | ||
134 | case "InstallPath": | ||
135 | this.Core.Write(ErrorMessages.ExpectedParentWithAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "Bundle")); | ||
136 | break; | ||
137 | case "Bitness": | ||
138 | var bitnessValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
139 | switch (bitnessValue) | ||
140 | { | ||
141 | case "always32": | ||
142 | win64 = false; | ||
143 | break; | ||
144 | case "always64": | ||
145 | win64 = true; | ||
146 | break; | ||
147 | case "default": | ||
148 | case "": | ||
149 | break; | ||
150 | default: | ||
151 | this.Core.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, bitnessValue, "default", "always32", "always64")); | ||
152 | break; | ||
153 | } | ||
154 | break; | ||
155 | default: | ||
156 | this.Core.UnexpectedAttribute(node, attrib); | ||
157 | break; | ||
158 | } | ||
159 | } | ||
160 | else | ||
161 | { | ||
162 | this.Core.ParseExtensionAttribute(node, attrib); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | this.Core.ParseForExtensionElements(node); | ||
167 | |||
168 | if (String.IsNullOrEmpty(name)) | ||
169 | { | ||
170 | name = node.Parent?.Attribute("Name")?.Value; | ||
171 | |||
172 | if (String.IsNullOrEmpty(name)) | ||
173 | { | ||
174 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name")); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | if (!String.IsNullOrEmpty(name) && !this.Core.IsValidLongFilename(name)) | ||
179 | { | ||
180 | this.Core.Write(CompilerErrors.IllegalName(sourceLineNumbers, node.Name.LocalName, name)); | ||
181 | } | ||
182 | |||
183 | if (String.IsNullOrEmpty(regid)) | ||
184 | { | ||
185 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Regid")); | ||
186 | } | ||
187 | else if (regid.Equals("example.com", StringComparison.OrdinalIgnoreCase)) | ||
188 | { | ||
189 | this.Core.Write(CompilerErrors.ExampleRegid(sourceLineNumbers, regid)); | ||
190 | return; | ||
191 | } | ||
192 | else if (id == null) | ||
193 | { | ||
194 | id = this.CreateTagId(regid); | ||
195 | } | ||
196 | |||
197 | if (String.IsNullOrEmpty(installDirectory)) | ||
198 | { | ||
199 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "InstallDirectory")); | ||
200 | } | ||
201 | |||
202 | if (!this.Core.EncounteredError) | ||
203 | { | ||
204 | var fileName = String.Concat(name, ".swidtag"); | ||
205 | |||
206 | this.Core.CreateSimpleReference(sourceLineNumbers, SymbolDefinitions.Directory, installDirectory); | ||
207 | this.Core.AddSymbol(new DirectorySymbol(sourceLineNumbers, id) | ||
208 | { | ||
209 | Name = "swidtag", | ||
210 | ParentDirectoryRef = installDirectory, | ||
211 | ComponentGuidGenerationSeed = "4BAD0C8B-3AF0-BFE3-CC83-094749A1C4B1" | ||
212 | }); | ||
213 | |||
214 | this.Core.AddSymbol(new ComponentSymbol(sourceLineNumbers, id) | ||
215 | { | ||
216 | ComponentId = "*", | ||
217 | DirectoryRef = id.Id, | ||
218 | KeyPath = id.Id, | ||
219 | KeyPathType = ComponentKeyPathType.File, | ||
220 | Location = ComponentLocation.LocalOnly, | ||
221 | Win64 = win64 | ||
222 | }); | ||
223 | |||
224 | this.Core.AddSymbol(new FileSymbol(sourceLineNumbers, id) | ||
225 | { | ||
226 | ComponentRef = id.Id, | ||
227 | Name = fileName, | ||
228 | DiskId = 1, | ||
229 | Attributes = FileSymbolAttributes.ReadOnly, | ||
230 | }); | ||
231 | |||
232 | if (!String.IsNullOrEmpty(feature)) | ||
233 | { | ||
234 | this.Core.CreateSimpleReference(sourceLineNumbers, SymbolDefinitions.Feature, feature); | ||
235 | } | ||
236 | else | ||
237 | { | ||
238 | feature = "WixSwidTag"; | ||
239 | this.Core.AddSymbol(new FeatureSymbol(sourceLineNumbers, new Identifier(AccessModifier.Private, feature)) | ||
240 | { | ||
241 | Title = "ISO/IEC 19770-2", | ||
242 | Level = 1, | ||
243 | InstallDefault = FeatureInstallDefault.Local, | ||
244 | Display = 0, | ||
245 | DisallowAdvertise = true, | ||
246 | DisallowAbsent = true, | ||
247 | }); | ||
248 | } | ||
249 | this.Core.CreateComplexReference(sourceLineNumbers, ComplexReferenceParentType.Feature, feature, null, ComplexReferenceChildType.Component, id.Id, true); | ||
250 | |||
251 | this.Core.EnsureTable(sourceLineNumbers, "SoftwareIdentificationTag"); | ||
252 | this.Core.AddSymbol(new WixProductTagSymbol(sourceLineNumbers, id) | ||
253 | { | ||
254 | FileRef = id.Id, | ||
255 | Regid = regid, | ||
256 | Name = name | ||
257 | }); | ||
258 | } | ||
259 | } | ||
260 | |||
261 | /// <summary> | ||
262 | /// Parses a TagRef element for Software Id Tag registration under a PatchFamily element. | ||
263 | /// </summary> | ||
264 | /// <param name="node">The element to parse.</param> | ||
265 | private void ParseTagRefElement(XElement node) | ||
266 | { | ||
267 | var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
268 | string regid = null; | ||
269 | |||
270 | foreach (var attrib in node.Attributes()) | ||
271 | { | ||
272 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) | ||
273 | { | ||
274 | switch (attrib.Name.LocalName) | ||
275 | { | ||
276 | case "Regid": | ||
277 | regid = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
278 | break; | ||
279 | default: | ||
280 | this.Core.UnexpectedAttribute(node, attrib); | ||
281 | break; | ||
282 | } | ||
283 | } | ||
284 | else | ||
285 | { | ||
286 | this.Core.ParseExtensionAttribute(node, attrib); | ||
287 | } | ||
288 | } | ||
289 | |||
290 | this.Core.ParseForExtensionElements(node); | ||
291 | |||
292 | if (String.IsNullOrEmpty(regid)) | ||
293 | { | ||
294 | this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Regid")); | ||
295 | } | ||
296 | else if (regid.Equals("example.com", StringComparison.OrdinalIgnoreCase)) | ||
297 | { | ||
298 | this.Core.Write(CompilerErrors.ExampleRegid(sourceLineNumbers, regid)); | ||
299 | } | ||
300 | |||
301 | if (!this.Core.EncounteredError) | ||
302 | { | ||
303 | var id = this.CreateTagId(regid); | ||
304 | |||
305 | this.Core.AddSymbol(new WixPatchRefSymbol(sourceLineNumbers, id) | ||
306 | { | ||
307 | Table = SymbolDefinitions.Component.Name, | ||
308 | PrimaryKeys = id.Id | ||
309 | }); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | private Identifier CreateTagId(string regid) => this.Core.CreateIdentifier("tag", regid, ".product.tag"); | ||
314 | } | ||
315 | } | ||
diff --git a/src/test/WixToolsetTest.CoreIntegration/SoftwareTagFixture.cs b/src/test/WixToolsetTest.CoreIntegration/SoftwareTagFixture.cs new file mode 100644 index 00000000..15276b18 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/SoftwareTagFixture.cs | |||
@@ -0,0 +1,100 @@ | |||
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 WixToolsetTest.CoreIntegration | ||
4 | { | ||
5 | using System.IO; | ||
6 | using System.Linq; | ||
7 | using System.Xml.Linq; | ||
8 | using WixBuildTools.TestSupport; | ||
9 | using WixToolset.Core.TestPackage; | ||
10 | using WixToolset.Data; | ||
11 | using Xunit; | ||
12 | |||
13 | public class SoftwareTagFixture | ||
14 | { | ||
15 | private static readonly XNamespace BurnManifestNamespace = "http://wixtoolset.org/schemas/v4/2008/Burn"; | ||
16 | private static readonly XNamespace SwidTagNamespace = "http://standards.iso.org/iso/19770/-2/2009/schema.xsd"; | ||
17 | |||
18 | [Fact] | ||
19 | public void CanBuildPackageWithTag() | ||
20 | { | ||
21 | var folder = TestData.Get(@"TestData\ProductTag"); | ||
22 | var build = new Builder(folder, null, new[] { folder }); | ||
23 | |||
24 | var results = build.BuildAndQuery(Build, "File", "SoftwareIdentificationTag"); | ||
25 | |||
26 | var replacePackageCodeStart = results[2].IndexOf("\tmsi:package/") + "\tmsi:package/".Length; | ||
27 | var replacePackageCodeEnd = results[2].IndexOf("\t", replacePackageCodeStart); | ||
28 | results[2] = results[2].Substring(0, replacePackageCodeStart) + "???" + results[2].Substring(replacePackageCodeEnd); | ||
29 | WixAssert.CompareLineByLine(new[] | ||
30 | { | ||
31 | "File:filF5_pLhBuF5b4N9XEo52g_hUM5Lo\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\texample.txt\t20\t\t\t512\t1", | ||
32 | "File:tagEYRYWwOt95punO7qPPAQ9p1GBpY\ttagEYRYWwOt95punO7qPPAQ9p1GBpY\trdcfonyt.swi|~TagTestPackage.swidtag\t449\t\t\t1\t2", | ||
33 | "SoftwareIdentificationTag:tagEYRYWwOt95punO7qPPAQ9p1GBpY\twixtoolset.org\tmsi:package/???\tmsi:upgrade/047730A5-30FE-4A62-A520-DA9381B8226A\t" | ||
34 | }, results.ToArray()); | ||
35 | } | ||
36 | |||
37 | [Fact] | ||
38 | public void CanBuildBundleWithTag() | ||
39 | { | ||
40 | var testDataFolder = TestData.Get(@"TestData"); | ||
41 | |||
42 | using (var fs = new DisposableFileSystem()) | ||
43 | { | ||
44 | var baseFolder = fs.GetFolder(); | ||
45 | var intermediateFolder = Path.Combine(baseFolder, "obj"); | ||
46 | |||
47 | var result = WixRunner.Execute(new[] | ||
48 | { | ||
49 | "build", | ||
50 | Path.Combine(testDataFolder, "ProductTag", "PackageWithTag.wxs"), | ||
51 | Path.Combine(testDataFolder, "ProductTag", "PackageComponents.wxs"), | ||
52 | "-loc", Path.Combine(testDataFolder, "ProductTag", "Package.en-us.wxl"), | ||
53 | "-bindpath", Path.Combine(testDataFolder, "ProductTag"), | ||
54 | "-intermediateFolder", Path.Combine(intermediateFolder, "package"), | ||
55 | "-o", Path.Combine(baseFolder, "package", @"test.msi") | ||
56 | }); | ||
57 | |||
58 | result.AssertSuccess(); | ||
59 | |||
60 | result = WixRunner.Execute(new[] | ||
61 | { | ||
62 | "build", | ||
63 | Path.Combine(testDataFolder, "BundleTag", "BundleWithTag.wxs"), | ||
64 | "-bindpath", Path.Combine(testDataFolder, "BundleTag"), | ||
65 | "-bindpath", Path.Combine(baseFolder, "package"), | ||
66 | "-intermediateFolder", intermediateFolder, | ||
67 | "-o", Path.Combine(baseFolder, @"bin\test.exe") | ||
68 | }); | ||
69 | |||
70 | result.AssertSuccess(); | ||
71 | |||
72 | Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.exe"))); | ||
73 | Assert.True(File.Exists(Path.Combine(baseFolder, @"bin\test.wixpdb"))); | ||
74 | |||
75 | using (var ouput = WixOutput.Read(Path.Combine(baseFolder, @"bin\test.wixpdb"))) | ||
76 | { | ||
77 | var badata = ouput.GetDataStream("wix-burndata.xml"); | ||
78 | var doc = XDocument.Load(badata); | ||
79 | |||
80 | var swidTag = doc.Root.Element(BurnManifestNamespace + "Registration").Element(BurnManifestNamespace + "SoftwareTag").Value; | ||
81 | |||
82 | var swidTagPath = Path.Combine(baseFolder, "test.swidtag"); | ||
83 | File.WriteAllText(swidTagPath, swidTag); | ||
84 | |||
85 | var docTag = XDocument.Load(swidTagPath); | ||
86 | var title = docTag.Root.Attribute("name").Value; | ||
87 | var version = docTag.Root.Attribute("version").Value; | ||
88 | Assert.Equal("~TagTestBundle", title); | ||
89 | Assert.Equal("4.3.2.1", version); | ||
90 | } | ||
91 | } | ||
92 | } | ||
93 | |||
94 | private static void Build(string[] args) | ||
95 | { | ||
96 | var result = WixRunner.Execute(args) | ||
97 | .AssertSuccess(); | ||
98 | } | ||
99 | } | ||
100 | } | ||
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/BundleTag/BundleWithTag.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/BundleTag/BundleWithTag.wxs new file mode 100644 index 00000000..f44fb7bc --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/BundleTag/BundleWithTag.wxs | |||
@@ -0,0 +1,15 @@ | |||
1 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" > | ||
2 | <Bundle Name="~TagTestBundle" Version="4.3.2.1" Manufacturer="Example Corporation" UpgradeCode="047730A5-30FE-4A62-A520-DA9381B8226A"> | ||
3 | <BootstrapperApplication> | ||
4 | <BootstrapperApplicationDll SourceFile="fakeba.dll" /> | ||
5 | </BootstrapperApplication> | ||
6 | |||
7 | <SoftwareTag Regid="wixtoolset.org" InstallPath="[ProgramFiles6432Folder]\Test\swidtag" /> | ||
8 | |||
9 | <Chain> | ||
10 | <MsiPackage SourceFile="test.msi"> | ||
11 | <MsiProperty Name="TEST" Value="1" /> | ||
12 | </MsiPackage> | ||
13 | </Chain> | ||
14 | </Bundle> | ||
15 | </Wix> | ||
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/BundleTag/fakeba.dll b/src/test/WixToolsetTest.CoreIntegration/TestData/BundleTag/fakeba.dll new file mode 100644 index 00000000..64061ea0 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/BundleTag/fakeba.dll | |||
@@ -0,0 +1 @@ | |||
This is fakeba.dll. \ No newline at end of file | |||
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/ProductTag/Package.en-us.wxl b/src/test/WixToolsetTest.CoreIntegration/TestData/ProductTag/Package.en-us.wxl new file mode 100644 index 00000000..38c12ac1 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/ProductTag/Package.en-us.wxl | |||
@@ -0,0 +1,11 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | |||
3 | <!-- | ||
4 | This file contains the declaration of all the localizable strings. | ||
5 | --> | ||
6 | <WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US"> | ||
7 | |||
8 | <String Id="DowngradeError">A newer version of [ProductName] is already installed.</String> | ||
9 | <String Id="FeatureTitle">MsiPackage</String> | ||
10 | |||
11 | </WixLocalization> | ||
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/ProductTag/PackageComponents.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/ProductTag/PackageComponents.wxs new file mode 100644 index 00000000..37a2c462 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/ProductTag/PackageComponents.wxs | |||
@@ -0,0 +1,10 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
3 | <Fragment> | ||
4 | <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER"> | ||
5 | <Component> | ||
6 | <File Source="example.txt" /> | ||
7 | </Component> | ||
8 | </ComponentGroup> | ||
9 | </Fragment> | ||
10 | </Wix> | ||
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/ProductTag/PackageWithTag.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/ProductTag/PackageWithTag.wxs new file mode 100644 index 00000000..17543c1a --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/ProductTag/PackageWithTag.wxs | |||
@@ -0,0 +1,20 @@ | |||
1 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
2 | <Package ProductCode="8738B0C5-C4AA-4634-8C03-11EAA2F1E15D" Name="~TagTestPackage" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a"> | ||
3 | |||
4 | <MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" /> | ||
5 | |||
6 | <Feature Id="ProductFeature" Title="!(loc.FeatureTitle)"> | ||
7 | <ComponentGroupRef Id="ProductComponents" /> | ||
8 | </Feature> | ||
9 | |||
10 | <SoftwareTag Regid="wixtoolset.org" InstallDirectory="INSTALLFOLDER" /> | ||
11 | </Package> | ||
12 | |||
13 | <Fragment> | ||
14 | <Directory Id="TARGETDIR" Name="SourceDir"> | ||
15 | <Directory Id="ProgramFilesFolder"> | ||
16 | <Directory Id="INSTALLFOLDER" Name="MsiPackage" /> | ||
17 | </Directory> | ||
18 | </Directory> | ||
19 | </Fragment> | ||
20 | </Wix> | ||
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/ProductTag/example.txt b/src/test/WixToolsetTest.CoreIntegration/TestData/ProductTag/example.txt new file mode 100644 index 00000000..1b4ffe8a --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/ProductTag/example.txt | |||
@@ -0,0 +1 @@ | |||
This is example.txt. \ No newline at end of file | |||