diff --git a/src/api/wix/WixToolset.Data/Symbols/HarvestFilesSymbol.cs b/src/api/wix/WixToolset.Data/Symbols/HarvestFilesSymbol.cs index a3123fc11..6b56625e3 100644 --- a/src/api/wix/WixToolset.Data/Symbols/HarvestFilesSymbol.cs +++ b/src/api/wix/WixToolset.Data/Symbols/HarvestFilesSymbol.cs @@ -16,6 +16,7 @@ public static partial class SymbolDefinitions new IntermediateFieldDefinition(nameof(HarvestFilesSymbolFields.ComplexReferenceParentType), IntermediateFieldType.String), new IntermediateFieldDefinition(nameof(HarvestFilesSymbolFields.ParentId), IntermediateFieldType.String), new IntermediateFieldDefinition(nameof(HarvestFilesSymbolFields.SourcePath), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(HarvestFilesSymbolFields.ModuleLanguage), IntermediateFieldType.String), }, typeof(HarvestFilesSymbol)); } @@ -31,6 +32,7 @@ public enum HarvestFilesSymbolFields ComplexReferenceParentType, ParentId, SourcePath, + ModuleLanguage, } public class HarvestFilesSymbol : IntermediateSymbol @@ -80,5 +82,11 @@ public string SourcePath get => (string)this.Fields[(int)HarvestFilesSymbolFields.SourcePath]; set => this.Set((int)HarvestFilesSymbolFields.SourcePath, value); } + + public string ModuleLanguage + { + get => (string)this.Fields[(int)HarvestFilesSymbolFields.ModuleLanguage]; + set => this.Set((int)HarvestFilesSymbolFields.ModuleLanguage, value); + } } } diff --git a/src/wix/WixToolset.Core/Compiler.cs b/src/wix/WixToolset.Core/Compiler.cs index 84f313449..3b3c62d4f 100644 --- a/src/wix/WixToolset.Core/Compiler.cs +++ b/src/wix/WixToolset.Core/Compiler.cs @@ -5689,7 +5689,12 @@ private void ParseNakedFileElement(XElement node, ComplexReferenceParentType par this.ParseFileElementChildren(node, fileSymbol, keyPath, win64); - if (ComplexReferenceParentType.Unknown != parentType && null != parentId) // if parent was provided, add a complex reference to that. + // if this is a module, automatically add this component to the references to ensure it gets in the ModuleComponents table + if (this.compilingModule) + { + this.Core.CreateComplexReference(sourceLineNumbers, ComplexReferenceParentType.Module, this.activeName, this.activeLanguage, ComplexReferenceChildType.Component, fileSymbol.Id.Id, false); + } + else if (ComplexReferenceParentType.Unknown != parentType && null != parentId) // if parent was provided, add a complex reference to that. { // If the naked file's component is defined directly under a feature, then mark the complex reference primary. this.Core.CreateComplexReference(sourceLineNumbers, parentType, parentId, null, ComplexReferenceChildType.Component, fileSymbol.Id.Id, ComplexReferenceParentType.Feature == parentType); @@ -5790,6 +5795,7 @@ private void ParseFilesElement(XElement node, ComplexReferenceParentType parentT ComplexReferenceParentType = parentType.ToString(), ParentId = parentId, SourcePath = sourcePath, + ModuleLanguage = this.compilingModule ? this.activeLanguage : null, }); } diff --git a/src/wix/WixToolset.Core/HarvestFilesCommand.cs b/src/wix/WixToolset.Core/HarvestFilesCommand.cs index 4acd9f240..ed78e808f 100644 --- a/src/wix/WixToolset.Core/HarvestFilesCommand.cs +++ b/src/wix/WixToolset.Core/HarvestFilesCommand.cs @@ -107,10 +107,15 @@ private void HarvestFiles(HarvestFilesSymbol harvestFile, IntermediateSection se Win64 = this.Context.Platform == Platform.ARM64 || this.Context.Platform == Platform.X64, }); - if (Enum.TryParse(harvestFile.ComplexReferenceParentType, out var parentType) + // if this is a module, automatically add this component to the references to ensure it gets in the ModuleComponents table + if (!String.IsNullOrEmpty(harvestFile.ModuleLanguage)) + { + this.ParseHelper.CreateComplexReference(section, harvestFile.SourceLineNumbers, ComplexReferenceParentType.Module, harvestFile.ParentId, harvestFile.ModuleLanguage, ComplexReferenceChildType.Component, id.Id, false); + } + else if (Enum.TryParse(harvestFile.ComplexReferenceParentType, out var parentType) && ComplexReferenceParentType.Unknown != parentType && null != harvestFile.ParentId) { - // If the parent was provided, add a complex reference to that, and, if + // If the parent was provided, add a complex reference to that, and, if // the Files is under a feature, then mark the complex reference primary. this.ParseHelper.CreateComplexReference(section, harvestFile.SourceLineNumbers, parentType, harvestFile.ParentId, null, ComplexReferenceChildType.Component, id.Id, ComplexReferenceParentType.Feature == parentType); } diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/HarvestFilesFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/HarvestFilesFixture.cs index 2630e2958..8e4964ded 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/HarvestFilesFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/HarvestFilesFixture.cs @@ -9,6 +9,7 @@ namespace WixToolsetTest.CoreIntegration using System.Linq; using WixInternal.Core.TestPackage; using WixInternal.TestSupport; + using WixToolset.Data.WindowsInstaller; using Xunit; public class HarvestFilesFixture @@ -225,16 +226,34 @@ public void CanHarvestFilesInFragments() [Fact] public void CanHarvestFilesInModules() { - var expected = new[] + var expectedFilesAndTargetPaths = new[] { - @"flsgrgAVAsCQ8tCCxfnbBNis66623c.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\test1.txt", + @"flsBvxG729t7hKBa4KOmfvNMPptZkM.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\test4.txt", @"flsDBWSWjpVSU3Zs33bREsJa2ygSQM.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\test2.txt", @"flsehdwEdXusUijRShuTszSxwf8joA.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\test3.txt", - @"flsBvxG729t7hKBa4KOmfvNMPptZkM.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\test4.txt", + @"flsgrgAVAsCQ8tCCxfnbBNis66623c.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\test1.txt", @"flskqOUVMfAE13k2h.ZkPhurwO4Y1c.E535B765_1019_4A4F_B3EA_AE28870E6D73=PFiles\MergeModule\notatest.txt", }; - Build("Module.wxs", (msiPath, _) => AssertFileIdsAndTargetPaths(msiPath, expected), isPackage: false); + var expectedModuleComponents = new[] + { + "ModuleComponents:flsBvxG729t7hKBa4KOmfvNMPptZkM.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033", + "ModuleComponents:flsDBWSWjpVSU3Zs33bREsJa2ygSQM.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033", + "ModuleComponents:flsehdwEdXusUijRShuTszSxwf8joA.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033", + "ModuleComponents:flsgrgAVAsCQ8tCCxfnbBNis66623c.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033", + "ModuleComponents:flskqOUVMfAE13k2h.ZkPhurwO4Y1c.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033", + }; + + Build("Module.wxs", (msiPath, _) => AssertModuleComponentsFileIdsAndTargetPaths(msiPath, expectedFilesAndTargetPaths, expectedModuleComponents), isMsi: false); + + static void AssertModuleComponentsFileIdsAndTargetPaths(string msiPath, string[] expectedFilesAndTargetPaths, string[] expectedModuleComponents) + { + AssertFileIdsAndTargetPaths(msiPath, expectedFilesAndTargetPaths); + + var query = Query.QueryDatabase(msiPath, new[] { "ModuleComponents" }); + + Assert.Equal(expectedModuleComponents, query); + } } [Fact] @@ -346,7 +365,7 @@ private static void AssertFileIdsAndTargetPaths(string msiPath, string[] expecte Assert.Equal(sortedExpected, actual); } - private static void Build(string file, Action tester, bool isPackage = true, bool warningsAsErrors = true, bool addUnnamedBindPath = false, params string[] additionalCommandLineArguments) + private static void Build(string file, Action tester, bool isMsi = true, bool warningsAsErrors = true, bool addUnnamedBindPath = false, params string[] additionalCommandLineArguments) { var folder = TestData.Get("TestData", "HarvestFiles"); @@ -355,7 +374,7 @@ private static void Build(string file, Action tester, b var baseFolder = fs.GetFolder(); var intermediateFolder = Path.Combine(baseFolder, "obj"); var binFolder = Path.Combine(baseFolder, "bin"); - var msiPath = Path.Combine(binFolder, isPackage ? "test.msi" : "test.msm"); + var msiPath = Path.Combine(binFolder, isMsi ? "test.msi" : "test.msm"); var arguments = new List() { diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/NakedFileFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/NakedFileFixture.cs index 6d874ff05..ae13421de 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/NakedFileFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/NakedFileFixture.cs @@ -2,6 +2,7 @@ namespace WixToolsetTest.CoreIntegration { + using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; @@ -82,6 +83,14 @@ public void CanBuildNakedFilesInModule() var rows = BuildAndQueryComponentAndFileTables("Module.wxs", isPackage: false); AssertFileComponentIds(2, rows); + + var expectedModuleComponents = new[] + { + "ModuleComponents:FILE1.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033", + "ModuleComponents:FILE2.E535B765_1019_4A4F_B3EA_AE28870E6D73\tMergeModule.E535B765_1019_4A4F_B3EA_AE28870E6D73\t1033", + }; + + Assert.Equal(expectedModuleComponents, rows.Where(row => row.StartsWith("ModuleComponents:"))); } [Fact] @@ -215,7 +224,14 @@ private static string[] BuildAndQueryComponentAndFileTables(string file, bool is { result.AssertSuccess(); - return Query.QueryDatabase(msiPath, new[] { "Component", "File" }) + var tables = new List { "Component", "File" }; + + if (!isPackage) + { + tables.Add("ModuleComponents"); + } + + return Query.QueryDatabase(msiPath, tables.ToArray()) .OrderBy(s => s) .ToArray(); }