Fix XmlConfig lookup logic.
Fixes https://github.com/wixtoolset/issues/issues/7377. Requires fix for https://github.com/wixtoolset/issues/issues/7444.
Bob Arnson committed
Apr 27, 2023 at 21:06 UTC
ab8d368fe8e7a41e503ec295b196035922293ef4
8 files changed
+134
-16
src/ext/Util/ca/XmlConfig.cpp
+4
-9
@@ -266,11 +266,11 @@ static HRESULT ProcessChanges(
266
// Keep track of where our next spot will be since our current node may be moved
267
pxfcNext = pxfc->pxfcNext;
268
269
- // With each node, check to see if it's element path matches the Id of some other node in the list
269
+ // With each node, check to see if its element path matches the Id of some other node in the list
270
pxfcCheck = *ppxfcHead;
271
while (pxfcCheck)
272
{
273
- if (pxfc->pwzElementId)
273
+ if (pxfc->pwzElementId && *pxfc->pwzElementId)
274
{
275
if (0 == lstrcmpW(pxfc->pwzElementId, pxfcCheck->wzId)
276
&& 0 == pxfc->iXmlFlags
@@ -315,11 +315,6 @@ static HRESULT ProcessChanges(
315
pxfcCheck->cAdditionalChanges = ++cAdditionalChanges;
316
}
317
}
318
- else
319
- {
320
- hr = E_NOTFOUND;
321
- ExitOnRootFailure(hr, "failed to find matching ElementId: %ls", pxfc->pwzElementId);
322
- }
318
}
319
320
pxfcCheck = pxfcCheck->pxfcNext;
@@ -402,10 +397,10 @@ static HRESULT WriteChangeData(
397
398
HRESULT hr = S_OK;
399
XML_CONFIG_CHANGE* pxfcAdditionalChanges = NULL;
405
- LPCWSTR wzElementPath = pxfc->pwzElementId ? pxfc->pwzElementId : pxfc->pwzElementPath;
400
+ LPCWSTR wzElementPath = pxfc->pwzElementId && *pxfc->pwzElementId ? pxfc->pwzElementId : pxfc->pwzElementPath;
401
402
hr = WcaWriteStringToCaData(wzElementPath, ppwzCustomActionData);
408
- ExitOnFailure(hr, "failed to write ElementPath to custom action data: %ls", wzElementPath);
403
+ ExitOnFailure(hr, "failed to write ElementId/ElementPath to custom action data: %ls", wzElementPath);
404
405
hr = WcaWriteStringToCaData(pxfc->pwzVerifyPath, ppwzCustomActionData);
406
ExitOnFailure(hr, "failed to write VerifyPath to custom action data: %ls", pxfc->pwzVerifyPath);
src/ext/Util/test/WixToolsetTest.Util/TestData/XmlConfig/Package.wxs
+16
-6
@@ -1,17 +1,27 @@
1
-<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
2
<Package Name="MsiPackage" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
<MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" />
4
5
<Feature Id="ProductFeature" Title="!(loc.FeatureTitle)">
6
+ <Component Directory="INSTALLFOLDER">
7
+ <File Id="MyXmlFile" Source="my.xml" />
8
+ </Component>
9
+
10
<Component Id="Del" Directory="INSTALLFOLDER" Guid="3613414c-11f5-40fa-a1f1-a0ba722a6895">
7
- <util:XmlConfig Id="DelElement" File="[INSTALLFOLDER]my.xml" Action="delete" Node="element" VerifyPath="xxx" ElementPath="//root/sub" On="install" Sequence="1" />
11
+ <util:XmlConfig Id="DelElement" File="[#MyXmlFile]" Action="delete" Node="element" VerifyPath="grandchild1" ElementPath="//root/child1" On="install" />
12
+ </Component>
13
+
14
+ <Component Id="Add" Directory="INSTALLFOLDER" Guid="30A9FF8B-7AC8-47F3-BB24-9EA81AA38856">
15
+ <util:XmlConfig Id="AddElement" File="[#MyXmlFile]" Action="create" Node="element" ElementPath="//root/child2" Name="grandchild3" On="install" Sequence="2" />
16
+ <util:XmlConfig ElementId="AddElement" File="[#MyXmlFile]" Name="TheAttribute1" Value="AttributeValue1" Sequence="3" />
17
+ <util:XmlConfig Id="AddAttribute2" ElementId="AddElement" File="[INSTALLFOLDER]my.xml" Name="TheAttribute2" Value="AttributeValue2" Sequence="4" />
18
</Component>
19
</Feature>
20
</Package>
21
22
<Fragment>
13
- <StandardDirectory Id="ProgramFilesFolder">
14
- <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
15
- </StandardDirectory>
16
- </Fragment>
23
+ <StandardDirectory Id="ProgramFilesFolder">
24
+ <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
25
+ </StandardDirectory>
26
+ </Fragment>
27
</Wix>
src/ext/Util/test/WixToolsetTest.Util/TestData/XmlConfig/my.xml
new
+11
@@ -0,0 +1,11 @@
1
+<root>
2
+ <child1>
3
+ <grandchild1>
4
+ </grandchild1>
5
+ </child1>
6
+
7
+ <child2>
8
+ <grandchild2>
9
+ </grandchild2>
10
+ </child2>
11
+</root>
src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs
+5
-1
@@ -10,6 +10,7 @@ namespace WixToolsetTest.Util
10
using WixToolset.Util;
11
using Xunit;
12
using System.Xml.Linq;
13
+ using System;
14
15
public class UtilExtensionFixture
16
{
@@ -293,7 +294,10 @@ namespace WixToolsetTest.Util
294
var results = build.BuildAndQuery(BuildX64, "Wix4XmlConfig");
295
WixAssert.CompareLineByLine(new[]
296
{
296
- "Wix4XmlConfig:DelElement\t[INSTALLFOLDER]my.xml\t\t//root/sub\txxx\t\t\t289\tDel\t1",
297
+ "Wix4XmlConfig:AddAttribute2\t[INSTALLFOLDER]my.xml\tAddElement\t\t\tTheAttribute2\tAttributeValue2\t0\tAdd\t4",
298
+ "Wix4XmlConfig:AddElement\t[#MyXmlFile]\t\t//root/child2\t\tgrandchild3\t\t273\tAdd\t2",
299
+ "Wix4XmlConfig:DelElement\t[#MyXmlFile]\t\t//root/child1\tgrandchild1\t\t\t289\tDel\t",
300
+ "Wix4XmlConfig:uxcPPF6g4HJEQpBLT9w9GT6SKyHWww\t[#MyXmlFile]\tAddElement\t\t\tTheAttribute1\tAttributeValue1\t0\tAdd\t3",
301
}, results.OrderBy(s => s).ToArray());
302
}
303
src/test/msi/TestData/XmlConfigTests/XmlConfig/Package.wxs
new
+27
@@ -0,0 +1,27 @@
1
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
2
+ <Package Name="XmlConfig" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3
+ <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
4
+
5
+ <Feature Id="ProductFeature" Title="XmlConfig">
6
+ <Component Directory="INSTALLFOLDER">
7
+ <File Id="MyXmlFile" Source="my.xml" />
8
+ </Component>
9
+
10
+ <Component Id="Del" Directory="INSTALLFOLDER" Guid="3613414c-11f5-40fa-a1f1-a0ba722a6895">
11
+ <util:XmlConfig Id="DelElement" File="[#MyXmlFile]" Action="delete" Node="element" VerifyPath="grandchild1" ElementPath="//root/child1" On="install" />
12
+ </Component>
13
+
14
+ <Component Id="Add" Directory="INSTALLFOLDER" Guid="30A9FF8B-7AC8-47F3-BB24-9EA81AA38856">
15
+ <util:XmlConfig Id="AddElement" File="[#MyXmlFile]" Action="create" Node="element" ElementPath="//root/child2" Name="grandchild3" On="install" Sequence="2" />
16
+ <util:XmlConfig ElementId="AddElement" File="[#MyXmlFile]" Name="TheAttribute1" Value="AttributeValue1" Sequence="3" />
17
+ <util:XmlConfig Id="AddAttribute2" ElementId="AddElement" File="[INSTALLFOLDER]my.xml" Name="TheAttribute2" Value="AttributeValue2" Sequence="4" />
18
+ </Component>
19
+ </Feature>
20
+ </Package>
21
+
22
+ <Fragment>
23
+ <StandardDirectory Id="ProgramFilesFolder">
24
+ <Directory Id="INSTALLFOLDER" Name="XmlConfig" />
25
+ </StandardDirectory>
26
+ </Fragment>
27
+</Wix>
src/test/msi/TestData/XmlConfigTests/XmlConfig/XmlConfig.wixproj
new
+6
@@ -0,0 +1,6 @@
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
+<Project Sdk="WixToolset.Sdk">
3
+ <ItemGroup>
4
+ <PackageReference Include="WixToolset.Util.wixext" />
5
+ </ItemGroup>
6
+</Project>
\ No newline at end of file
src/test/msi/TestData/XmlConfigTests/XmlConfig/my.xml
new
+11
@@ -0,0 +1,11 @@
1
+<root>
2
+ <child1>
3
+ <grandchild1>
4
+ </grandchild1>
5
+ </child1>
6
+
7
+ <child2>
8
+ <grandchild2>
9
+ </grandchild2>
10
+ </child2>
11
+</root>
src/test/msi/WixToolsetTest.MsiE2E/XmlConfigTests.cs
new
+54
@@ -0,0 +1,54 @@
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.MsiE2E;
4
+
5
+using System;
6
+using System.IO;
7
+using System.Xml.Linq;
8
+using WixTestTools;
9
+using Xunit;
10
+using Xunit.Abstractions;
11
+
12
+public class XmlConfigTests : MsiE2ETests
13
+{
14
+ public XmlConfigTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper)
15
+ {
16
+ }
17
+
18
+ [RuntimeFact]
19
+ public void CanModifyXmlFileWithXmlConfig()
20
+ {
21
+ var product = this.CreatePackageInstaller("XmlConfig");
22
+
23
+ product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
24
+
25
+ // Validate the expected changes in my.xml.
26
+ var myXmlPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "XmlConfig", "my.xml");
27
+ var content = File.ReadAllText(myXmlPath);
28
+ var xDoc = XDocument.Parse(content);
29
+
30
+ var xRoot = xDoc.Element("root");
31
+ var xChild1 = xRoot.Element("child1");
32
+ Assert.NotNull(xChild1);
33
+
34
+ var xGrandchild1 = xChild1.Element("grandchild1");
35
+ Assert.Null(xGrandchild1);
36
+
37
+ var xChild2 = xRoot.Element("child2");
38
+ Assert.NotNull(xChild2);
39
+
40
+ var xGrandchild3 = xChild2.Element("grandchild3");
41
+ Assert.NotNull(xGrandchild3);
42
+ Assert.True(xGrandchild3.HasAttributes);
43
+
44
+ var xAttribute1 = xGrandchild3.Attribute("TheAttribute1");
45
+ Assert.NotNull(xAttribute1);
46
+ Assert.Equal("AttributeValue1", xAttribute1.Value);
47
+
48
+ var xAttribute2 = xGrandchild3.Attribute("TheAttribute2");
49
+ Assert.NotNull(xAttribute2);
50
+ Assert.Equal("AttributeValue2", xAttribute2.Value);
51
+
52
+ product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
53
+ }
54
+}