Magicked files in modules need complex references.
Magic files (naked `File`s and `Files`) that are direct children of a `Module` need complex references from the generated component to that module, to ensure that they're wired up correctly as module components. Fixes https://github.com/wixtoolset/issues/issues/8860
Bob Arnson committed
Dec 22, 2024 at 22:44 UTC
28a2c0e963897ddc61e6673bcb93e10b9696375f
5 files changed
+64
-10
src/api/wix/WixToolset.Data/Symbols/HarvestFilesSymbol.cs
+8
@@ -16,6 +16,7 @@ namespace WixToolset.Data
16
new IntermediateFieldDefinition(nameof(HarvestFilesSymbolFields.ComplexReferenceParentType), IntermediateFieldType.String),
17
new IntermediateFieldDefinition(nameof(HarvestFilesSymbolFields.ParentId), IntermediateFieldType.String),
18
new IntermediateFieldDefinition(nameof(HarvestFilesSymbolFields.SourcePath), IntermediateFieldType.String),
19
+ new IntermediateFieldDefinition(nameof(HarvestFilesSymbolFields.ModuleLanguage), IntermediateFieldType.String),
20
},
21
typeof(HarvestFilesSymbol));
22
}
@@ -31,6 +32,7 @@ namespace WixToolset.Data.Symbols
32
ComplexReferenceParentType,
33
ParentId,
34
SourcePath,
35
+ ModuleLanguage,
36
}
37
38
public class HarvestFilesSymbol : IntermediateSymbol
@@ -80,5 +82,11 @@ namespace WixToolset.Data.Symbols
82
get => (string)this.Fields[(int)HarvestFilesSymbolFields.SourcePath];
83
set => this.Set((int)HarvestFilesSymbolFields.SourcePath, value);
84
}
85
+
86
+ public string ModuleLanguage
87
+ {
88
+ get => (string)this.Fields[(int)HarvestFilesSymbolFields.ModuleLanguage];
89
+ set => this.Set((int)HarvestFilesSymbolFields.ModuleLanguage, value);
90
+ }
91
}
92
}
src/wix/WixToolset.Core/Compiler.cs
+7
-1
@@ -5689,7 +5689,12 @@ namespace WixToolset.Core
5689
5690
this.ParseFileElementChildren(node, fileSymbol, keyPath, win64);
5691
5692
- if (ComplexReferenceParentType.Unknown != parentType && null != parentId) // if parent was provided, add a complex reference to that.
5692
+ // if this is a module, automatically add this component to the references to ensure it gets in the ModuleComponents table
5693
+ if (this.compilingModule)
5694
+ {
5695
+ this.Core.CreateComplexReference(sourceLineNumbers, ComplexReferenceParentType.Module, this.activeName, this.activeLanguage, ComplexReferenceChildType.Component, fileSymbol.Id.Id, false);
5696
+ }
5697
+ else if (ComplexReferenceParentType.Unknown != parentType && null != parentId) // if parent was provided, add a complex reference to that.
5698
{
5699
// If the naked file's component is defined directly under a feature, then mark the complex reference primary.
5700
this.Core.CreateComplexReference(sourceLineNumbers, parentType, parentId, null, ComplexReferenceChildType.Component, fileSymbol.Id.Id, ComplexReferenceParentType.Feature == parentType);
@@ -5790,6 +5795,7 @@ namespace WixToolset.Core
5795
ComplexReferenceParentType = parentType.ToString(),
5796
ParentId = parentId,
5797
SourcePath = sourcePath,
5798
+ ModuleLanguage = this.compilingModule ? this.activeLanguage : null,
5799
});
5800
}
5801
src/wix/WixToolset.Core/HarvestFilesCommand.cs
+7
-2
@@ -107,10 +107,15 @@ namespace WixToolset.Core
107
Win64 = this.Context.Platform == Platform.ARM64 || this.Context.Platform == Platform.X64,
108
});
109
110
- if (Enum.TryParse<ComplexReferenceParentType>(harvestFile.ComplexReferenceParentType, out var parentType)
110
+ // if this is a module, automatically add this component to the references to ensure it gets in the ModuleComponents table
111
+ if (!String.IsNullOrEmpty(harvestFile.ModuleLanguage))
112
+ {
113
+ this.ParseHelper.CreateComplexReference(section, harvestFile.SourceLineNumbers, ComplexReferenceParentType.Module, harvestFile.ParentId, harvestFile.ModuleLanguage, ComplexReferenceChildType.Component, id.Id, false);
114
+ }
115
+ else if (Enum.TryParse<ComplexReferenceParentType>(harvestFile.ComplexReferenceParentType, out var parentType)
116
&& ComplexReferenceParentType.Unknown != parentType && null != harvestFile.ParentId)
117
{
113
- // If the parent was provided, add a complex reference to that, and, if
118
+ // If the parent was provided, add a complex reference to that, and, if
119
// the Files is under a feature, then mark the complex reference primary.
120
this.ParseHelper.CreateComplexReference(section, harvestFile.SourceLineNumbers, parentType, harvestFile.ParentId, null, ComplexReferenceChildType.Component, id.Id, ComplexReferenceParentType.Feature == parentType);
121
}
src/wix/test/WixToolsetTest.CoreIntegration/HarvestFilesFixture.cs
+25
-6
@@ -9,6 +9,7 @@ namespace WixToolsetTest.CoreIntegration
9
using System.Linq;
10
using WixInternal.Core.TestPackage;
11
using WixInternal.TestSupport;
12
+ using WixToolset.Data.WindowsInstaller;
13
using Xunit;
14
15
public class HarvestFilesFixture
@@ -225,16 +226,34 @@ namespace WixToolsetTest.CoreIntegration
226
[Fact]
227
public void CanHarvestFilesInModules()
228
{
228
- var expected = new[]
229
+ var expectedFilesAndTargetPaths = new[]
230
{
230
- @"flsgrgAVAsCQ8tCCxfnbBNis66623c.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\test1.txt",
231
+ @"flsBvxG729t7hKBa4KOmfvNMPptZkM.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\test4.txt",
232
@"flsDBWSWjpVSU3Zs33bREsJa2ygSQM.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\test2.txt",
233
@"flsehdwEdXusUijRShuTszSxwf8joA.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\test3.txt",
233
- @"flsBvxG729t7hKBa4KOmfvNMPptZkM.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\test4.txt",
234
+ @"flsgrgAVAsCQ8tCCxfnbBNis66623c.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\test1.txt",
235
@"flskqOUVMfAE13k2h.ZkPhurwO4Y1c.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\notatest.txt",
236
};
237
237
- Build("Module.wxs", (msiPath, _) => AssertFileIdsAndTargetPaths(msiPath, expected), isPackage: false);
238
+ var expectedModuleComponents = new[]
239
+ {
240
+ "ModuleComponents:flsBvxG729t7hKBa4KOmfvNMPptZkM.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033",
241
+ "ModuleComponents:flsDBWSWjpVSU3Zs33bREsJa2ygSQM.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033",
242
+ "ModuleComponents:flsehdwEdXusUijRShuTszSxwf8joA.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033",
243
+ "ModuleComponents:flsgrgAVAsCQ8tCCxfnbBNis66623c.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033",
244
+ "ModuleComponents:flskqOUVMfAE13k2h.ZkPhurwO4Y1c.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033",
245
+ };
246
+
247
+ Build("Module.wxs", (msiPath, _) => AssertModuleComponentsFileIdsAndTargetPaths(msiPath, expectedFilesAndTargetPaths, expectedModuleComponents), isMsi: false);
248
+
249
+ static void AssertModuleComponentsFileIdsAndTargetPaths(string msiPath, string[] expectedFilesAndTargetPaths, string[] expectedModuleComponents)
250
+ {
251
+ AssertFileIdsAndTargetPaths(msiPath, expectedFilesAndTargetPaths);
252
+
253
+ var query = Query.QueryDatabase(msiPath, new[] { "ModuleComponents" });
254
+
255
+ Assert.Equal(expectedModuleComponents, query);
256
+ }
257
}
258
259
[Fact]
@@ -346,7 +365,7 @@ namespace WixToolsetTest.CoreIntegration
365
Assert.Equal(sortedExpected, actual);
366
}
367
349
- private static void Build(string file, Action<string, WixRunnerResult> tester, bool isPackage = true, bool warningsAsErrors = true, bool addUnnamedBindPath = false, params string[] additionalCommandLineArguments)
368
+ private static void Build(string file, Action<string, WixRunnerResult> tester, bool isMsi = true, bool warningsAsErrors = true, bool addUnnamedBindPath = false, params string[] additionalCommandLineArguments)
369
{
370
var folder = TestData.Get("TestData", "HarvestFiles");
371
@@ -355,7 +374,7 @@ namespace WixToolsetTest.CoreIntegration
374
var baseFolder = fs.GetFolder();
375
var intermediateFolder = Path.Combine(baseFolder, "obj");
376
var binFolder = Path.Combine(baseFolder, "bin");
358
- var msiPath = Path.Combine(binFolder, isPackage ? "test.msi" : "test.msm");
377
+ var msiPath = Path.Combine(binFolder, isMsi ? "test.msi" : "test.msm");
378
379
var arguments = new List<string>()
380
{
src/wix/test/WixToolsetTest.CoreIntegration/NakedFileFixture.cs
+17
-1
@@ -2,6 +2,7 @@
2
3
namespace WixToolsetTest.CoreIntegration
4
{
5
+ using System.Collections.Generic;
6
using System.Data;
7
using System.IO;
8
using System.Linq;
@@ -82,6 +83,14 @@ namespace WixToolsetTest.CoreIntegration
83
var rows = BuildAndQueryComponentAndFileTables("Module.wxs", isPackage: false);
84
85
AssertFileComponentIds(2, rows);
86
+
87
+ var expectedModuleComponents = new[]
88
+ {
89
+ "ModuleComponents:FILE1.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033",
90
+ "ModuleComponents:FILE2.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033",
91
+ };
92
+
93
+ Assert.Equal(expectedModuleComponents, rows.Where(row => row.StartsWith("ModuleComponents:")));
94
}
95
96
[Fact]
@@ -215,7 +224,14 @@ namespace WixToolsetTest.CoreIntegration
224
{
225
result.AssertSuccess();
226
218
- return Query.QueryDatabase(msiPath, new[] { "Component", "File" })
227
+ var tables = new List<string> { "Component", "File" };
228
+
229
+ if (!isPackage)
230
+ {
231
+ tables.Add("ModuleComponents");
232
+ }
233
+
234
+ return Query.QueryDatabase(msiPath, tables.ToArray())
235
.OrderBy(s => s)
236
.ToArray();
237
}