@joebigelow / wix / commits / 457c1447

Introduce Value attribute on MultiString/MultiStringValue elements

Rob Mensching committed Jun 17, 2020 at 12:10 UTC 457c144720964a7f50b1d184e6b19faa930e970e
5 files changed +168 -70
src/WixToolset.Core/Compiler_2.cs
+38 -5
@@ -1964,18 +1964,15 @@ namespace WixToolset.Core
1964 {
1965 switch (child.Name.LocalName)
1966 {
1967 + case "MultiString":
1968 case "MultiStringValue":
1969 if (RegistryValueType.MultiString != valueType && null != value)
1970 {
1971 this.Core.Write(ErrorMessages.RegistryMultipleValuesWithoutMultiString(sourceLineNumbers, node.Name.LocalName, "Value", child.Name.LocalName, "Type"));
1972 }
1972 - else if (null == value)
1973 - {
1974 - value = Common.GetInnerText(child);
1975 - }
1973 else
1974 {
1978 - value = String.Concat(value, "[~]", Common.GetInnerText(child));
1975 + value = this.ParseRegistryMultiStringElement(child, value);
1976 }
1977 break;
1978 case "Permission":
@@ -2069,6 +2066,42 @@ namespace WixToolset.Core
2066 return keyPath;
2067 }
2068
2069 + private string ParseRegistryMultiStringElement(XElement node, string value)
2070 + {
2071 + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
2072 + string multiStringValue = null;
2073 +
2074 + foreach (var attrib in node.Attributes())
2075 + {
2076 + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
2077 + {
2078 + switch (attrib.Name.LocalName)
2079 + {
2080 + case "Value":
2081 + multiStringValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2082 + break;
2083 + default:
2084 + this.Core.UnexpectedAttribute(node, attrib);
2085 + break;
2086 + }
2087 + }
2088 + }
2089 +
2090 + if (multiStringValue == null)
2091 + {
2092 + multiStringValue = Common.GetInnerText(node);
2093 + }
2094 +
2095 + if (multiStringValue == null)
2096 + {
2097 + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Value"));
2098 + }
2099 +
2100 + this.Core.ParseForExtensionElements(node);
2101 +
2102 + return (null == value) ? multiStringValue : String.Concat(value, "[~]", multiStringValue);
2103 + }
2104 +
2105 /// <summary>
2106 /// Parses a RemoveRegistryKey element.
2107 /// </summary>
src/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs
-65
@@ -804,71 +804,6 @@ namespace WixToolsetTest.CoreIntegration
804 }
805 }
806
807 - [Fact]
808 - public void PopulatesRegistryTableFromRegistryValue()
809 - {
810 - var folder = TestData.Get(@"TestData");
811 -
812 - using (var fs = new DisposableFileSystem())
813 - {
814 - var baseFolder = fs.GetFolder();
815 - var intermediateFolder = Path.Combine(baseFolder, "obj");
816 - var msiPath = Path.Combine(baseFolder, @"bin\test.msi");
817 -
818 - var result = WixRunner.Execute(new[]
819 - {
820 - "build",
821 - Path.Combine(folder, "Registry", "RegistryValue.wxs"),
822 - Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"),
823 - "-bindpath", Path.Combine(folder, "SingleFile", "data"),
824 - "-intermediateFolder", intermediateFolder,
825 - "-o", msiPath
826 - });
827 -
828 - result.AssertSuccess();
829 -
830 - Assert.True(File.Exists(msiPath));
831 - var results = Query.QueryDatabase(msiPath, new[] { "Registry" });
832 - Assert.Equal(new[]
833 - {
834 - "Registry:reg04OIwIchl.9ZTjisTT6NzGSsQSM\t2\tPath\\To\\AnotherKey\tSecret\t#x\tMiscComponent",
835 - "Registry:regEblTuusqFNSUQNy88zaP_UA5kIY\t2\tPath\\To\\Key\t\t1.0.1234.123\tMiscComponent",
836 - }, results);
837 - }
838 - }
839 -
840 - [Fact]
841 - public void PopulatesRegistryTableFromRemoveRegistryKey()
842 - {
843 - var folder = TestData.Get(@"TestData");
844 -
845 - using (var fs = new DisposableFileSystem())
846 - {
847 - var baseFolder = fs.GetFolder();
848 - var intermediateFolder = Path.Combine(baseFolder, "obj");
849 - var msiPath = Path.Combine(baseFolder, @"bin\test.msi");
850 -
851 - var result = WixRunner.Execute(new[]
852 - {
853 - "build",
854 - Path.Combine(folder, "Registry", "RemoveRegistryKey.wxs"),
855 - Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"),
856 - "-bindpath", Path.Combine(folder, "SingleFile", "data"),
857 - "-intermediateFolder", intermediateFolder,
858 - "-o", msiPath
859 - });
860 -
861 - result.AssertSuccess();
862 -
863 - Assert.True(File.Exists(msiPath));
864 - var results = Query.QueryDatabase(msiPath, new[] { "Registry" });
865 - Assert.Equal(new[]
866 - {
867 - "Registry:RemoveAKeyName\t2\tAKeyName\t-\t\tRemoveRegistryKeyComp",
868 - }, results);
869 - }
870 - }
871 -
807 [Fact]
808 public void PopulatesReserveCostTable()
809 {
src/test/WixToolsetTest.CoreIntegration/RegistryFixture.cs new
+114
@@ -0,0 +1,114 @@
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;
6 + using System.Collections.Generic;
7 + using System.IO;
8 + using System.Linq;
9 + using System.Text;
10 + using WixBuildTools.TestSupport;
11 + using WixToolset.Core.TestPackage;
12 + using WixToolset.Data;
13 + using Xunit;
14 +
15 + public class RegistryFixture
16 + {
17 + [Fact]
18 + public void PopulatesRegistryTableFromRegistryValue()
19 + {
20 + var folder = TestData.Get(@"TestData");
21 +
22 + using (var fs = new DisposableFileSystem())
23 + {
24 + var baseFolder = fs.GetFolder();
25 + var intermediateFolder = Path.Combine(baseFolder, "obj");
26 + var msiPath = Path.Combine(baseFolder, @"bin\test.msi");
27 +
28 + var result = WixRunner.Execute(new[]
29 + {
30 + "build",
31 + Path.Combine(folder, "Registry", "RegistryValue.wxs"),
32 + Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"),
33 + "-bindpath", Path.Combine(folder, "SingleFile", "data"),
34 + "-intermediateFolder", intermediateFolder,
35 + "-o", msiPath
36 + });
37 +
38 + result.AssertSuccess();
39 +
40 + Assert.True(File.Exists(msiPath));
41 + var results = Query.QueryDatabase(msiPath, new[] { "Registry" });
42 + Assert.Equal(new[]
43 + {
44 + "Registry:reg04OIwIchl.9ZTjisTT6NzGSsQSM\t2\tPath\\To\\AnotherKey\tSecret\t#x\tMiscComponent",
45 + "Registry:regEblTuusqFNSUQNy88zaP_UA5kIY\t2\tPath\\To\\Key\t\t1.0.1234.123\tMiscComponent",
46 + }, results);
47 + }
48 + }
49 +
50 + [Fact]
51 + public void PopulatesRegistryTableFromRegistryValueMultiString()
52 + {
53 + var folder = TestData.Get(@"TestData");
54 +
55 + using (var fs = new DisposableFileSystem())
56 + {
57 + var baseFolder = fs.GetFolder();
58 + var intermediateFolder = Path.Combine(baseFolder, "obj");
59 + var msiPath = Path.Combine(baseFolder, @"bin\test.msi");
60 +
61 + var result = WixRunner.Execute(new[]
62 + {
63 + "build",
64 + Path.Combine(folder, "Registry", "RegistryValueMultiString.wxs"),
65 + Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"),
66 + "-bindpath", Path.Combine(folder, "SingleFile", "data"),
67 + "-intermediateFolder", intermediateFolder,
68 + "-o", msiPath
69 + });
70 +
71 + result.AssertSuccess();
72 +
73 + var results = Query.QueryDatabase(msiPath, new[] { "Registry" });
74 + Assert.Equal(new[]
75 + {
76 + "Registry:regitq_Wx9LfvJuNSc2un6gIHAzr4A\t2\tPath\\To\\AnotherKey\tSecret\t#x\tMultiStringComponent",
77 + "Registry:regmeTJMpOD41igfxhTcUVZ7kNG1Mo\t2\tPath\\To\\Key\t\ta[~]b[~]c\tMultiStringComponent",
78 + }, results);
79 + }
80 + }
81 +
82 + [Fact]
83 + public void PopulatesRegistryTableFromRemoveRegistryKey()
84 + {
85 + var folder = TestData.Get(@"TestData");
86 +
87 + using (var fs = new DisposableFileSystem())
88 + {
89 + var baseFolder = fs.GetFolder();
90 + var intermediateFolder = Path.Combine(baseFolder, "obj");
91 + var msiPath = Path.Combine(baseFolder, @"bin\test.msi");
92 +
93 + var result = WixRunner.Execute(new[]
94 + {
95 + "build",
96 + Path.Combine(folder, "Registry", "RemoveRegistryKey.wxs"),
97 + Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"),
98 + "-bindpath", Path.Combine(folder, "SingleFile", "data"),
99 + "-intermediateFolder", intermediateFolder,
100 + "-o", msiPath
101 + });
102 +
103 + result.AssertSuccess();
104 +
105 + Assert.True(File.Exists(msiPath));
106 + var results = Query.QueryDatabase(msiPath, new[] { "Registry" });
107 + Assert.Equal(new[]
108 + {
109 + "Registry:RemoveAKeyName\t2\tAKeyName\t-\t\tRemoveRegistryKeyComp",
110 + }, results);
111 + }
112 + }
113 + }
114 +}
src/test/WixToolsetTest.CoreIntegration/TestData/Registry/RegistryValueMultiString.wxs new
+15
@@ -0,0 +1,15 @@
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 Id="MultiStringComponent" Guid="7C40C257-AB36-4B8C-8FD1-C56E0AC4AAEF">
6 + <RegistryValue Root="HKLM" Key="Path\To\Key" Type="multiString" KeyPath="yes">
7 + <MultiString Value="a" />
8 + <MultiStringValue Value="b" />
9 + <MultiString Value="c" />
10 + </RegistryValue>
11 + <RegistryValue Root="HKLM" Key="Path\To\AnotherKey" Name="Secret" Type="binary" />
12 + </Component>
13 + </ComponentGroup>
14 + </Fragment>
15 +</Wix>
src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj
+1
@@ -74,6 +74,7 @@
74 <Content Include="TestData\ProductWithComponentGroupRef\MinimalComponentGroup.wxs" CopyToOutputDirectory="PreserveNewest" />
75 <Content Include="TestData\ProductWithComponentGroupRef\Product.wxs" CopyToOutputDirectory="PreserveNewest" />
76 <Content Include="TestData\Registry\RegistryValue.wxs" CopyToOutputDirectory="PreserveNewest" />
77 + <Content Include="TestData\Registry\RegistryValueMultiString.wxs" CopyToOutputDirectory="PreserveNewest" />
78 <Content Include="TestData\Registry\RemoveRegistryKey.wxs" CopyToOutputDirectory="PreserveNewest" />
79 <Content Include="TestData\ReserveCost\ReserveCost.wxs" CopyToOutputDirectory="PreserveNewest" />
80 <Content Include="TestData\SequenceTables\DecompiledSequenceTables.wxs" CopyToOutputDirectory="PreserveNewest" />