@joebigelow / wix-1 / commits / b500f7ae

Fix ParsePossibleKeyPathExtensionElement extension point to support more than registry

Fixes 7208

Rob Mensching committed Feb 9, 2023 at 21:59 UTC b500f7ae7113039c878555ec622d551854f891e2
6 files changed +211 -7
src/wix/WixToolset.Core/Compiler.cs
+26 -7
@@ -2422,14 +2422,33 @@ namespace WixToolset.Core
2422 {
2423 keyPathSet = possibleKeyPath.Explicit ? YesNoType.Yes : YesNoType.NotSet;
2424
2425 - if (!String.IsNullOrEmpty(possibleKeyPath.Id))
2425 + switch (possibleKeyPath.Type)
2426 {
2427 - keyPossible = possibleKeyPath.Id;
2428 - }
2429 -
2430 - if (PossibleKeyPathType.Registry == possibleKeyPath.Type || PossibleKeyPathType.RegistryFormatted == possibleKeyPath.Type)
2431 - {
2432 - keyBit = ComponentKeyPathType.Registry; //MsiInterop.MsidbComponentAttributesRegistryKeyPath;
2427 + case PossibleKeyPathType.File:
2428 + keyBit = ComponentKeyPathType.File;
2429 + keyPossible = possibleKeyPath.Id;
2430 + break;
2431 + case PossibleKeyPathType.Directory:
2432 + keyBit = ComponentKeyPathType.Directory;
2433 + keyPossible = String.Empty;
2434 + break;
2435 +
2436 + case PossibleKeyPathType.OdbcDataSource:
2437 + keyBit = ComponentKeyPathType.OdbcDataSource;
2438 + keyPossible = possibleKeyPath.Id;
2439 + break;
2440 +
2441 + case PossibleKeyPathType.Registry:
2442 + case PossibleKeyPathType.RegistryFormatted:
2443 + keyBit = ComponentKeyPathType.Registry;
2444 + keyPossible = possibleKeyPath.Id;
2445 + break;
2446 +
2447 + case PossibleKeyPathType.None:
2448 + default:
2449 + keyBit = null;
2450 + keyPossible = null;
2451 + break;
2452 }
2453 }
2454 }
src/wix/test/Example.Extension/ExampleCompilerExtension.cs
+72
@@ -7,6 +7,7 @@ namespace Example.Extension
7 using System.Xml.Linq;
8 using WixToolset.Data;
9 using WixToolset.Extensibility;
10 + using WixToolset.Extensibility.Data;
11
12 internal class ExampleCompilerExtension : BaseCompilerExtension
13 {
@@ -57,6 +58,24 @@ namespace Example.Extension
58 }
59 }
60
61 + public override IComponentKeyPath ParsePossibleKeyPathElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary<string, string> context)
62 + {
63 + switch (parentElement.Name.LocalName)
64 + {
65 + case "Component":
66 + var componentId = context["ComponentId"];
67 +
68 + switch (element.Name.LocalName)
69 + {
70 + case "ExampleSetKeyPath":
71 + return this.ParseExampleSetKeyPathElement(intermediate, section, element, componentId);
72 + }
73 + break;
74 + }
75 +
76 + return base.ParsePossibleKeyPathElement(intermediate, section, parentElement, element, context);
77 + }
78 +
79 private void ParseExampleElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
80 {
81 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
@@ -101,6 +120,59 @@ namespace Example.Extension
120 }
121 }
122
123 + private IComponentKeyPath ParseExampleSetKeyPathElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
124 + {
125 + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
126 + string file = null;
127 + string reg = null;
128 + var explicitly = false;
129 +
130 + foreach (var attrib in element.Attributes())
131 + {
132 + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
133 + {
134 + switch (attrib.Name.LocalName)
135 + {
136 + case "File":
137 + file = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
138 + break;
139 +
140 + case "Registry":
141 + reg = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
142 + break;
143 +
144 + case "Explicitly":
145 + explicitly = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib) == YesNoType.Yes;
146 + break;
147 +
148 + default:
149 + this.ParseHelper.UnexpectedAttribute(element, attrib);
150 + break;
151 + }
152 + }
153 + else
154 + {
155 + this.ParseAttribute(intermediate, section, element, attrib, null);
156 + }
157 + }
158 +
159 + if (file == null && reg == null)
160 + {
161 + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "File", "Registry", true));
162 + }
163 +
164 + if (!this.Messaging.EncounteredError)
165 + {
166 + var componentKeyPath = this.CreateComponentKeyPath();
167 + componentKeyPath.Id = file ?? reg;
168 + componentKeyPath.Explicit = explicitly;
169 + componentKeyPath.Type = String.IsNullOrEmpty(file) ? PossibleKeyPathType.Registry : PossibleKeyPathType.File;
170 + return componentKeyPath;
171 + }
172 +
173 + return null;
174 + }
175 +
176 private void ParseExampleEnsureTableElement(Intermediate intermediate, IntermediateSection section, XElement element)
177 {
178 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
src/wix/test/WixToolsetTest.CoreIntegration/ExtensionFixture.cs
+60
@@ -96,6 +96,66 @@ namespace WixToolsetTest.CoreIntegration
96 }
97 }
98
99 + [Fact]
100 + public void CanBuildWithExampleExtensionWithFilePossibleKeyPath()
101 + {
102 + var folder = TestData.Get("TestData", "ExampleExtensionUsingPossibleKeyPath");
103 +
104 + using (var fs = new DisposableFileSystem())
105 + {
106 + var intermediateFolder = fs.GetFolder();
107 +
108 + var result = WixRunner.Execute(new[]
109 + {
110 + "build",
111 + Path.Combine(folder, "PackageWithFile.wxs"),
112 + "-ext", ExtensionPaths.ExampleExtensionPath,
113 + "-bindpath", Path.Combine(folder, "data"),
114 + "-intermediateFolder", intermediateFolder,
115 + "-o", Path.Combine(intermediateFolder, "bin", "extest.msi")
116 + });
117 +
118 + result.AssertSuccess();
119 +
120 + var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, "bin", "extest.wixpdb"));
121 + var section = intermediate.Sections.Single();
122 +
123 + var componentSymbol = section.Symbols.OfType<ComponentSymbol>().Single();
124 + Assert.Equal("ExampleFile", componentSymbol.KeyPath);
125 + Assert.Equal(ComponentKeyPathType.File, componentSymbol.KeyPathType);
126 + }
127 + }
128 +
129 + [Fact]
130 + public void CanBuildWithExampleExtensionWithRegistryPossibleKeyPath()
131 + {
132 + var folder = TestData.Get("TestData", "ExampleExtensionUsingPossibleKeyPath");
133 +
134 + using (var fs = new DisposableFileSystem())
135 + {
136 + var intermediateFolder = fs.GetFolder();
137 +
138 + var result = WixRunner.Execute(new[]
139 + {
140 + "build",
141 + Path.Combine(folder, "PackageWithRegistry.wxs"),
142 + "-ext", ExtensionPaths.ExampleExtensionPath,
143 + "-bindpath", Path.Combine(folder, "data"),
144 + "-intermediateFolder", intermediateFolder,
145 + "-o", Path.Combine(intermediateFolder, "bin", "extest.msi")
146 + });
147 +
148 + result.AssertSuccess();
149 +
150 + var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, "bin", "extest.wixpdb"));
151 + var section = intermediate.Sections.Single();
152 +
153 + var componentSymbol = section.Symbols.OfType<ComponentSymbol>().Single();
154 + Assert.Equal("RegMadeKeyPath", componentSymbol.KeyPath);
155 + Assert.Equal(ComponentKeyPathType.Registry, componentSymbol.KeyPathType);
156 + }
157 + }
158 +
159 [Fact]
160 public void CanParseCommandLineWithExtension()
161 {
src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtensionUsingPossibleKeyPath/PackageWithFile.wxs new
+27
@@ -0,0 +1,27 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
2 + xmlns:ex="http://www.example.com/scheams/v1/wxs">
3 + <Package Name="MsiPackage" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a" Compressed="no">
4 + <MajorUpgrade DowngradeErrorMessage="Don't upgrade" />
5 +
6 + <Feature Id="ProductFeature">
7 + <ComponentGroupRef Id="ProductComponents" />
8 + </Feature>
9 + </Package>
10 +
11 + <Fragment>
12 + <StandardDirectory Id="ProgramFilesFolder">
13 + <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
14 + </StandardDirectory>
15 + </Fragment>
16 +
17 + <Fragment>
18 + <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
19 + <Component>
20 + <RegistryValue Id="RegMadeKeyPath" Root="HKLM" Key="SOFTWARE\Example Corporation" Name="Test" Value="Thing" />
21 +
22 + <ex:ExampleSetKeyPath File="ExampleFile" Explicitly="yes" />
23 + <File Id="ExampleFile" Source="example.txt" />
24 + </Component>
25 + </ComponentGroup>
26 + </Fragment>
27 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtensionUsingPossibleKeyPath/PackageWithRegistry.wxs new
+25
@@ -0,0 +1,25 @@
1 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
2 + xmlns:ex="http://www.example.com/scheams/v1/wxs">
3 + <Package Name="MsiPackage With Registry" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a" Compressed="no">
4 + <MajorUpgrade DowngradeErrorMessage="Don't upgrade" />
5 +
6 + <Feature Id="ProductFeature">
7 + <ComponentGroupRef Id="ProductComponents" />
8 + </Feature>
9 + </Package>
10 +
11 + <Fragment>
12 + <StandardDirectory Id="ProgramFilesFolder">
13 + <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
14 + </StandardDirectory>
15 + </Fragment>
16 +
17 + <Fragment>
18 + <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
19 + <Component>
20 + <ex:ExampleSetKeyPath Registry="RegMadeKeyPath" />
21 + <RegistryValue Id="RegMadeKeyPath" Root="HKLM" Key="SOFTWARE\Example Corporation" Name="Test" Value="Thing" KeyPath="no" />
22 + </Component>
23 + </ComponentGroup>
24 + </Fragment>
25 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtensionUsingPossibleKeyPath/data/example.txt new
+1
@@ -0,0 +1 @@
1 +This is example.txt.