From 7ce477c6863c74ef0a50d117d8c28b2f19971b42 Mon Sep 17 00:00:00 2001 From: Bob Arnson Date: Sat, 29 Jan 2022 23:44:11 -0500 Subject: Add compiler extension to handle platforms. Custom actions to print EULA and validate install directories are defined in WixUIExtension compiler extension, to handle platform-specific custom actions referred to from `DoAction` control events. This is the least-worst solution, given the `DoAction` approach used in the WixUI authoring and anyone customizing a WixUI set. --- src/ext/UI/ca/uica.vcxproj | 16 +++ .../TestData/WixUI_Advanced/Package.wxs | 6 +- .../TestData/WixUI_FeatureTree/Package.wxs | 4 +- .../TestData/WixUI_InstallDir/Package.wxs | 4 +- .../TestData/WixUI_Minimal/Package.wxs | 4 +- .../TestData/WixUI_Mondo/Package.wxs | 4 +- .../test/WixToolsetTest.UI/UIExtensionFixture.cs | 99 +++++++++++------ src/ext/UI/wixext/UICompiler.cs | 118 +++++++++++++++++++++ src/ext/UI/wixext/UIExtensionFactory.cs | 1 + src/ext/UI/wixlib/Common_Platform.wxi | 17 ++- src/ext/UI/wixlib/Common_arm64.wxs | 7 ++ src/ext/UI/wixlib/Common_x64.wxs | 7 ++ src/ext/UI/wixlib/WixUI_Advanced.wxs | 1 - src/ext/UI/wixlib/WixUI_FeatureTree.wxs | 1 - src/ext/UI/wixlib/WixUI_InstallDir.wxs | 1 - src/ext/UI/wixlib/WixUI_Minimal.wxs | 1 - src/ext/UI/wixlib/WixUI_Mondo.wxs | 1 - src/ext/UI/wixlib/caSuffix.wxi | 27 ----- src/ext/UI/wixlib/ui.wixproj | 4 +- .../TestData/FilesInUseTests/PackageA/PackageA.wxs | 4 +- .../TestData/WixprojLibraryVcxprojDll/Library.wxs | 4 +- .../Package.wxs | 2 - ...xprojPackageCsprojWebApplicationNetCore.wixproj | 1 - .../WixprojPackageVcxprojWindowsApp/Package.wxs | 2 - .../WixprojPackageVcxprojWindowsApp.wixproj | 2 - src/wix/WixToolset.Converters/WixConverter.cs | 36 +++++-- .../UIExtensionFixture.cs | 59 +++++++++++ 27 files changed, 327 insertions(+), 106 deletions(-) create mode 100644 src/ext/UI/wixext/UICompiler.cs create mode 100644 src/ext/UI/wixlib/Common_arm64.wxs create mode 100644 src/ext/UI/wixlib/Common_x64.wxs delete mode 100644 src/ext/UI/wixlib/caSuffix.wxi create mode 100644 src/wix/test/WixToolsetTest.Converters/UIExtensionFixture.cs diff --git a/src/ext/UI/ca/uica.vcxproj b/src/ext/UI/ca/uica.vcxproj index e06b7572..27f0faa7 100644 --- a/src/ext/UI/ca/uica.vcxproj +++ b/src/ext/UI/ca/uica.vcxproj @@ -11,6 +11,22 @@ Release Win32 + + Debug + x64 + + + Release + x64 + + + Debug + ARM64 + + + Release + ARM64 + diff --git a/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_Advanced/Package.wxs b/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_Advanced/Package.wxs index 5ce4b00f..c22328e6 100644 --- a/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_Advanced/Package.wxs +++ b/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_Advanced/Package.wxs @@ -1,5 +1,5 @@ - - + + @@ -12,7 +12,7 @@ - + diff --git a/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_FeatureTree/Package.wxs b/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_FeatureTree/Package.wxs index aff1c077..7c4db223 100644 --- a/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_FeatureTree/Package.wxs +++ b/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_FeatureTree/Package.wxs @@ -1,4 +1,4 @@ - + @@ -12,7 +12,7 @@ - + diff --git a/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_InstallDir/Package.wxs b/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_InstallDir/Package.wxs index 7c2ceae0..b6f2344a 100644 --- a/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_InstallDir/Package.wxs +++ b/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_InstallDir/Package.wxs @@ -1,4 +1,4 @@ - + @@ -12,7 +12,7 @@ - + diff --git a/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_Minimal/Package.wxs b/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_Minimal/Package.wxs index d2ff256c..962be579 100644 --- a/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_Minimal/Package.wxs +++ b/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_Minimal/Package.wxs @@ -1,4 +1,4 @@ - + @@ -12,7 +12,7 @@ - + diff --git a/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_Mondo/Package.wxs b/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_Mondo/Package.wxs index 8d5a856a..9eca9790 100644 --- a/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_Mondo/Package.wxs +++ b/src/ext/UI/test/WixToolsetTest.UI/TestData/WixUI_Mondo/Package.wxs @@ -1,4 +1,4 @@ - + @@ -12,7 +12,7 @@ - + diff --git a/src/ext/UI/test/WixToolsetTest.UI/UIExtensionFixture.cs b/src/ext/UI/test/WixToolsetTest.UI/UIExtensionFixture.cs index 778bfb64..4ab7ec3f 100644 --- a/src/ext/UI/test/WixToolsetTest.UI/UIExtensionFixture.cs +++ b/src/ext/UI/test/WixToolsetTest.UI/UIExtensionFixture.cs @@ -7,8 +7,6 @@ namespace WixToolsetTest.UI using System.Linq; using WixBuildTools.TestSupport; using WixToolset.Core.TestPackage; - using WixToolset.Data; - using WixToolset.Data.Symbols; using WixToolset.Data.WindowsInstaller; using WixToolset.UI; using Xunit; @@ -22,11 +20,48 @@ namespace WixToolsetTest.UI var bindFolder = TestData.Get(@"TestData\data"); var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder }); - var results = build.BuildAndQuery(Build, "Property"); - WixAssert.CompareLineByLine(new[] - { - "Property:WixUI_Mode\tAdvanced", - }, results.Where(s => s.StartsWith("Property:WixUI_Mode")).ToArray()); + var results = build.BuildAndQuery(Build, "Dialog", "CustomAction"); + Assert.Single(results, result => result.StartsWith("Dialog:AdvancedWelcomeEulaDlg\t")); + Assert.Single(results, result => result.StartsWith("CustomAction:WixSetDefaultPerMachineFolder\t")); + Assert.Single(results, result => result.StartsWith("CustomAction:WixSetDefaultPerUserFolder\t")); + Assert.Single(results, result => result.StartsWith("CustomAction:WixSetPerMachineFolder\t")); + Assert.Single(results, result => result.StartsWith("CustomAction:WixSetPerUserFolder\t")); + Assert.Single(results, result => result.StartsWith("CustomAction:WixUIPrintEula\t65\tWixUiCa_X86\t")); + Assert.Single(results, result => result.StartsWith("CustomAction:WixUIValidatePath\t65\tWixUiCa_X86\t")); + } + + [Fact] + public void CanBuildUsingWixUIAdvancedX64() + { + var folder = TestData.Get(@"TestData\WixUI_Advanced"); + var bindFolder = TestData.Get(@"TestData\data"); + var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder }); + + var results = build.BuildAndQuery(BuildX64, "Dialog", "CustomAction"); + Assert.Single(results, result => result.StartsWith("Dialog:AdvancedWelcomeEulaDlg\t")); + Assert.Single(results, result => result.StartsWith("CustomAction:WixSetDefaultPerMachineFolder\t")); + Assert.Single(results, result => result.StartsWith("CustomAction:WixSetDefaultPerUserFolder\t")); + Assert.Single(results, result => result.StartsWith("CustomAction:WixSetPerMachineFolder\t")); + Assert.Single(results, result => result.StartsWith("CustomAction:WixSetPerUserFolder\t")); + Assert.Single(results, result => result.StartsWith("CustomAction:WixUIPrintEula\t65\tWixUiCa_X64\t")); + Assert.Single(results, result => result.StartsWith("CustomAction:WixUIValidatePath\t65\tWixUiCa_X64\t")); + } + + [Fact] + public void CanBuildUsingWixUIAdvancedARM64() + { + var folder = TestData.Get(@"TestData\WixUI_Advanced"); + var bindFolder = TestData.Get(@"TestData\data"); + var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder }); + + var results = build.BuildAndQuery(BuildARM64, "Dialog", "CustomAction"); + Assert.Single(results, result => result.StartsWith("Dialog:AdvancedWelcomeEulaDlg\t")); + Assert.Single(results, result => result.StartsWith("CustomAction:WixSetDefaultPerMachineFolder\t")); + Assert.Single(results, result => result.StartsWith("CustomAction:WixSetDefaultPerUserFolder\t")); + Assert.Single(results, result => result.StartsWith("CustomAction:WixSetPerMachineFolder\t")); + Assert.Single(results, result => result.StartsWith("CustomAction:WixSetPerUserFolder\t")); + Assert.Single(results, result => result.StartsWith("CustomAction:WixUIPrintEula\t65\tWixUiCa_A64\t")); + Assert.Single(results, result => result.StartsWith("CustomAction:WixUIValidatePath\t65\tWixUiCa_A64\t")); } [Fact] @@ -36,11 +71,10 @@ namespace WixToolsetTest.UI var bindFolder = TestData.Get(@"TestData\data"); var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder }); - var results = build.BuildAndQuery(Build, "Property"); - WixAssert.CompareLineByLine(new[] - { - "Property:WixUI_Mode\tFeatureTree", - }, results.Where(s => s.StartsWith("Property:WixUI_Mode")).ToArray()); + var results = build.BuildAndQuery(Build, "Dialog", "CustomAction"); + Assert.Single(results, result => result.StartsWith("Dialog:WelcomeDlg\t")); + Assert.Single(results, result => result.StartsWith("Dialog:CustomizeDlg\t")); + Assert.Empty(results.Where(result => result.StartsWith("Dialog:SetupTypeDlg\t"))); } [Fact] @@ -50,11 +84,8 @@ namespace WixToolsetTest.UI var bindFolder = TestData.Get(@"TestData\data"); var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder }); - var results = build.BuildAndQuery(Build, "Property"); - WixAssert.CompareLineByLine(new[] - { - "Property:WixUI_Mode\tInstallDir", - }, results.Where(s => s.StartsWith("Property:WixUI_Mode")).ToArray()); + var results = build.BuildAndQuery(Build, "Dialog", "CustomAction"); + Assert.Single(results, result => result.StartsWith("Dialog:InstallDirDlg\t")); } [Fact] @@ -64,11 +95,8 @@ namespace WixToolsetTest.UI var bindFolder = TestData.Get(@"TestData\data"); var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder }); - var results = build.BuildAndQuery(Build, "Property"); - WixAssert.CompareLineByLine(new[] - { - "Property:WixUI_Mode\tMinimal", - }, results.Where(s => s.StartsWith("Property:WixUI_Mode")).ToArray()); + var results = build.BuildAndQuery(Build, "Dialog", "CustomAction"); + Assert.Single(results, result => result.StartsWith("Dialog:WelcomeEulaDlg\t")); } [Fact] @@ -92,10 +120,8 @@ namespace WixToolsetTest.UI }); var wid = WindowsInstallerData.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb")); - var propertyTable = wid.Tables["Property"]; - - var propertyRow = propertyTable.Rows.Single(r => r.GetPrimaryKey() == "WixUI_Mode"); - WixAssert.StringEqual("Minimal", propertyRow.FieldAsString(1)); + var dialogTable = wid.Tables["Dialog"]; + var dialogRow = dialogTable.Rows.Single(r => r.GetPrimaryKey() == "WelcomeEulaDlg"); } } @@ -106,11 +132,10 @@ namespace WixToolsetTest.UI var bindFolder = TestData.Get(@"TestData\data"); var build = new Builder(folder, typeof(UIExtensionFactory), new[] { bindFolder }); - var results = build.BuildAndQuery(Build, "Property"); - WixAssert.CompareLineByLine(new[] - { - "Property:WixUI_Mode\tMondo", - }, results.Where(s => s.StartsWith("Property:WixUI_Mode")).ToArray()); + var results = build.BuildAndQuery(Build, "Dialog", "CustomAction"); + Assert.Single(results, result => result.StartsWith("Dialog:WelcomeDlg\t")); + Assert.Single(results, result => result.StartsWith("Dialog:CustomizeDlg\t")); + Assert.Single(results, result => result.StartsWith("Dialog:SetupTypeDlg\t")); } [Fact] @@ -133,6 +158,18 @@ namespace WixToolsetTest.UI .AssertSuccess(); } + private static void BuildX64(string[] args) + { + var result = WixRunner.Execute(args.Concat(new[] { "-arch", "x64" }).ToArray()) + .AssertSuccess(); + } + + private static void BuildARM64(string[] args) + { + var result = WixRunner.Execute(args.Concat(new[] { "-arch", "arm64" }).ToArray()) + .AssertSuccess(); + } + private static void BuildInGerman(string[] args) { var localizedArgs = args.Append("-culture").Append("de-DE").ToArray(); diff --git a/src/ext/UI/wixext/UICompiler.cs b/src/ext/UI/wixext/UICompiler.cs new file mode 100644 index 00000000..46b856c0 --- /dev/null +++ b/src/ext/UI/wixext/UICompiler.cs @@ -0,0 +1,118 @@ +// 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. + +namespace WixToolset.UI +{ + using System; + using System.Collections.Generic; + using System.Xml.Linq; + using WixToolset.Data; + using WixToolset.Data.Symbols; + using WixToolset.Extensibility; + + /// + /// The decompiler for the WiX Toolset UI Extension. + /// + public sealed class UICompiler : BaseCompilerExtension + { + public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/ui"; + + /// + /// Processes an element for the Compiler. + /// + /// Source line number for the parent element. + /// Parent element of element to process. + /// Element to process. + /// Extra information about the context in which this element is being parsed. + public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary context) + { + switch (parentElement.Name.LocalName) + { + case "Fragment": + case "Module": + case "PatchFamily": + case "Package": + case "UI": + switch (element.Name.LocalName) + { + case "WixUI": + this.ParseWixUIElement(intermediate, section, element); + break; + default: + this.ParseHelper.UnexpectedElement(parentElement, element); + break; + } + break; + default: + this.ParseHelper.UnexpectedElement(parentElement, element); + break; + } + } + + /// + /// Parses a WixUI element. + /// + private void ParseWixUIElement(Intermediate intermediate, IntermediateSection section, XElement element) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + string id = null; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + id = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + break; + default: + this.ParseHelper.UnexpectedAttribute(element, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + if (null == id) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Id")); + } + else + { + this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixUI, id); + + // Because these custom actions are "scheduled" via `DoAction` control events, we have to create the + // custom action definitions here, so the `DoAction` references are static and the targets are + // dynamically created to properly reflect the platform-specific DLL and avoid having duplicate ids + // in the UI .wixlib. + var platform = this.Context.Platform == Platform.ARM64 ? "A64" : this.Context.Platform.ToString(); + var source = $"WixUiCa_{platform}"; + + section.AddSymbol(new CustomActionSymbol(sourceLineNumbers, new Identifier(AccessModifier.Global, "WixUIPrintEula")) + { + TargetType = CustomActionTargetType.Dll, + Target = "PrintEula", + SourceType = CustomActionSourceType.Binary, + Source = source, + IgnoreResult = true, + ExecutionType = CustomActionExecutionType.Immediate, + }); + + section.AddSymbol(new CustomActionSymbol(sourceLineNumbers, new Identifier(AccessModifier.Global, "WixUIValidatePath")) + { + TargetType = CustomActionTargetType.Dll, + Target = "ValidatePath", + SourceType = CustomActionSourceType.Binary, + Source = source, + IgnoreResult = true, + ExecutionType = CustomActionExecutionType.Immediate, + }); + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + } + } +} diff --git a/src/ext/UI/wixext/UIExtensionFactory.cs b/src/ext/UI/wixext/UIExtensionFactory.cs index 141aa39f..a16a9899 100644 --- a/src/ext/UI/wixext/UIExtensionFactory.cs +++ b/src/ext/UI/wixext/UIExtensionFactory.cs @@ -11,6 +11,7 @@ namespace WixToolset.UI protected override IReadOnlyCollection ExtensionTypes => new[] { typeof(UIExtensionData), + typeof(UICompiler), }; } } diff --git a/src/ext/UI/wixlib/Common_Platform.wxi b/src/ext/UI/wixlib/Common_Platform.wxi index ffaa7114..0c03629c 100644 --- a/src/ext/UI/wixlib/Common_Platform.wxi +++ b/src/ext/UI/wixlib/Common_Platform.wxi @@ -2,18 +2,15 @@ - - - - - + - - - - + - + diff --git a/src/ext/UI/wixlib/Common_arm64.wxs b/src/ext/UI/wixlib/Common_arm64.wxs new file mode 100644 index 00000000..61dd5ddd --- /dev/null +++ b/src/ext/UI/wixlib/Common_arm64.wxs @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/ext/UI/wixlib/Common_x64.wxs b/src/ext/UI/wixlib/Common_x64.wxs new file mode 100644 index 00000000..89204605 --- /dev/null +++ b/src/ext/UI/wixlib/Common_x64.wxs @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/ext/UI/wixlib/WixUI_Advanced.wxs b/src/ext/UI/wixlib/WixUI_Advanced.wxs index 7d1f4df0..2ea7a97d 100644 --- a/src/ext/UI/wixlib/WixUI_Advanced.wxs +++ b/src/ext/UI/wixlib/WixUI_Advanced.wxs @@ -53,7 +53,6 @@ Todo: - diff --git a/src/ext/UI/wixlib/WixUI_FeatureTree.wxs b/src/ext/UI/wixlib/WixUI_FeatureTree.wxs index e999f2fe..6f36bdb8 100644 --- a/src/ext/UI/wixlib/WixUI_FeatureTree.wxs +++ b/src/ext/UI/wixlib/WixUI_FeatureTree.wxs @@ -29,7 +29,6 @@ Patch dialog sequence: - diff --git a/src/ext/UI/wixlib/WixUI_InstallDir.wxs b/src/ext/UI/wixlib/WixUI_InstallDir.wxs index afe7820f..f8eb3b11 100644 --- a/src/ext/UI/wixlib/WixUI_InstallDir.wxs +++ b/src/ext/UI/wixlib/WixUI_InstallDir.wxs @@ -30,7 +30,6 @@ Patch dialog sequence: - diff --git a/src/ext/UI/wixlib/WixUI_Minimal.wxs b/src/ext/UI/wixlib/WixUI_Minimal.wxs index 08dba96d..8ac9751f 100644 --- a/src/ext/UI/wixlib/WixUI_Minimal.wxs +++ b/src/ext/UI/wixlib/WixUI_Minimal.wxs @@ -24,7 +24,6 @@ Patch dialog sequence: - diff --git a/src/ext/UI/wixlib/WixUI_Mondo.wxs b/src/ext/UI/wixlib/WixUI_Mondo.wxs index 2d53b9dd..6a4b15b1 100644 --- a/src/ext/UI/wixlib/WixUI_Mondo.wxs +++ b/src/ext/UI/wixlib/WixUI_Mondo.wxs @@ -31,7 +31,6 @@ Patch dialog sequence: - diff --git a/src/ext/UI/wixlib/caSuffix.wxi b/src/ext/UI/wixlib/caSuffix.wxi deleted file mode 100644 index 18436269..00000000 --- a/src/ext/UI/wixlib/caSuffix.wxi +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ext/UI/wixlib/ui.wixproj b/src/ext/UI/wixlib/ui.wixproj index 2b335f01..ead77af4 100644 --- a/src/ext/UI/wixlib/ui.wixproj +++ b/src/ext/UI/wixlib/ui.wixproj @@ -27,7 +27,9 @@ - + + + diff --git a/src/test/burn/TestData/FilesInUseTests/PackageA/PackageA.wxs b/src/test/burn/TestData/FilesInUseTests/PackageA/PackageA.wxs index a96c2a11..0902ff1a 100644 --- a/src/test/burn/TestData/FilesInUseTests/PackageA/PackageA.wxs +++ b/src/test/burn/TestData/FilesInUseTests/PackageA/PackageA.wxs @@ -1,10 +1,10 @@  - + - + diff --git a/src/test/wix/TestData/WixprojLibraryVcxprojDll/Library.wxs b/src/test/wix/TestData/WixprojLibraryVcxprojDll/Library.wxs index eed46112..f61c0ebe 100644 --- a/src/test/wix/TestData/WixprojLibraryVcxprojDll/Library.wxs +++ b/src/test/wix/TestData/WixprojLibraryVcxprojDll/Library.wxs @@ -1,11 +1,9 @@ - + - - diff --git a/src/test/wix/TestData/WixprojPackageCsprojWebApplicationNetCore/Package.wxs b/src/test/wix/TestData/WixprojPackageCsprojWebApplicationNetCore/Package.wxs index 17a5b29b..c228bb33 100644 --- a/src/test/wix/TestData/WixprojPackageCsprojWebApplicationNetCore/Package.wxs +++ b/src/test/wix/TestData/WixprojPackageCsprojWebApplicationNetCore/Package.wxs @@ -12,7 +12,5 @@ - - diff --git a/src/test/wix/TestData/WixprojPackageCsprojWebApplicationNetCore/WixprojPackageCsprojWebApplicationNetCore.wixproj b/src/test/wix/TestData/WixprojPackageCsprojWebApplicationNetCore/WixprojPackageCsprojWebApplicationNetCore.wixproj index f9852465..c9f56d1d 100644 --- a/src/test/wix/TestData/WixprojPackageCsprojWebApplicationNetCore/WixprojPackageCsprojWebApplicationNetCore.wixproj +++ b/src/test/wix/TestData/WixprojPackageCsprojWebApplicationNetCore/WixprojPackageCsprojWebApplicationNetCore.wixproj @@ -11,7 +11,6 @@ - diff --git a/src/test/wix/TestData/WixprojPackageVcxprojWindowsApp/Package.wxs b/src/test/wix/TestData/WixprojPackageVcxprojWindowsApp/Package.wxs index 00ef4d05..c0370683 100644 --- a/src/test/wix/TestData/WixprojPackageVcxprojWindowsApp/Package.wxs +++ b/src/test/wix/TestData/WixprojPackageVcxprojWindowsApp/Package.wxs @@ -16,7 +16,5 @@ - - diff --git a/src/test/wix/TestData/WixprojPackageVcxprojWindowsApp/WixprojPackageVcxprojWindowsApp.wixproj b/src/test/wix/TestData/WixprojPackageVcxprojWindowsApp/WixprojPackageVcxprojWindowsApp.wixproj index 84deecb6..7dc26a2d 100644 --- a/src/test/wix/TestData/WixprojPackageVcxprojWindowsApp/WixprojPackageVcxprojWindowsApp.wixproj +++ b/src/test/wix/TestData/WixprojPackageVcxprojWindowsApp/WixprojPackageVcxprojWindowsApp.wixproj @@ -5,7 +5,5 @@ - - diff --git a/src/wix/WixToolset.Converters/WixConverter.cs b/src/wix/WixToolset.Converters/WixConverter.cs index 7bd2f81a..b8a83326 100644 --- a/src/wix/WixToolset.Converters/WixConverter.cs +++ b/src/wix/WixToolset.Converters/WixConverter.cs @@ -57,6 +57,7 @@ namespace WixToolset.Converters private static readonly XNamespace WixBalNamespace = "http://wixtoolset.org/schemas/v4/wxs/bal"; private static readonly XNamespace WixDependencyNamespace = "http://wixtoolset.org/schemas/v4/wxs/dependency"; private static readonly XNamespace WixFirewallNamespace = "http://wixtoolset.org/schemas/v4/wxs/firewall"; + private static readonly XNamespace WixUiNamespace = "http://wixtoolset.org/schemas/v4/wxs/ui"; private static readonly XNamespace WixUtilNamespace = "http://wixtoolset.org/schemas/v4/wxs/util"; private static readonly XNamespace WixVSNamespace = "http://wixtoolset.org/schemas/v4/wxs/vs"; @@ -142,6 +143,7 @@ namespace WixToolset.Converters private static readonly XName UtilXmlConfigElementName = WixUtilNamespace + "XmlConfig"; private static readonly XName CustomActionElementName = WixNamespace + "CustomAction"; private static readonly XName CustomActionRefElementName = WixNamespace + "CustomActionRef"; + private static readonly XName UIRefElementName = WixNamespace + "UIRef"; private static readonly XName PropertyElementName = WixNamespace + "Property"; private static readonly XName Wix4ElementName = WixNamespace + "Wix"; private static readonly XName Wix3ElementName = Wix3Namespace + "Wix"; @@ -259,6 +261,7 @@ namespace WixToolset.Converters { WixConverter.WixElementWithoutNamespaceName, this.ConvertElementWithoutNamespace }, { WixConverter.IncludeElementWithoutNamespaceName, this.ConvertElementWithoutNamespace }, { WixConverter.VerbElementName, this.ConvertVerbElement }, + { WixConverter.UIRefElementName, this.ConvertUIRefElement }, }; this.Messaging = messaging; @@ -1275,14 +1278,14 @@ namespace WixToolset.Converters xPackage.SetAttributeValue("Scope", "perUser"); break; case "elevated": + { + var xAllUsers = xPackage.Elements(PropertyElementName).SingleOrDefault(p => p.Attribute("Id")?.Value == "ALLUSERS"); + if (xAllUsers?.Attribute("Value")?.Value == "1") { - var xAllUsers = xPackage.Elements(PropertyElementName).SingleOrDefault(p => p.Attribute("Id")?.Value == "ALLUSERS"); - if (xAllUsers?.Attribute("Value")?.Value == "1") - { - xAllUsers?.Remove(); - } + xAllUsers?.Remove(); } - break; + } + break; } xInstallPrivileges?.Remove(); @@ -1439,7 +1442,7 @@ namespace WixToolset.Converters } if (!String.IsNullOrEmpty(newElementName) - && this.OnError(ConverterTestType.ReferencesReplaced, element, "Custom action and property reference {0} have been replaced with strongly-typed elements.", id)) + && this.OnError(ConverterTestType.ReferencesReplaced, element, "UI, custom action, and property reference {0} has been replaced with strongly-typed element.", id)) { this.XRoot.SetAttributeValue(XNamespace.Xmlns + newNamespaceName, newNamespace.NamespaceName); @@ -1452,6 +1455,21 @@ namespace WixToolset.Converters } } + private void ConvertUIRefElement(XElement element) + { + var id = element.Attribute("Id")?.Value; + + if (id?.StartsWith("WixUI_") == true + && this.OnError(ConverterTestType.ReferencesReplaced, element, "UI, custom action, and property reference {0} has been replaced with strongly-typed element.", id)) + { + this.XRoot.SetAttributeValue(XNamespace.Xmlns + "ui", WixUiNamespace.NamespaceName); + + element.AddBeforeSelf(new XElement(WixUiNamespace + "WixUI", new XAttribute("Id", id))); + + element.Remove(); + } + } + private void ConvertCustomActionRefElement(XElement element) { var newElementName = String.Empty; @@ -1471,7 +1489,7 @@ namespace WixToolset.Converters } if (!String.IsNullOrEmpty(newElementName) - && this.OnError(ConverterTestType.ReferencesReplaced, element, "Custom action and property reference {0} have been replaced with strongly-typed elements.", id)) + && this.OnError(ConverterTestType.ReferencesReplaced, element, "UI, custom action, and property reference {0} has been replaced with strongly-typed element.", id)) { element.AddAfterSelf(new XElement(WixUtilNamespace + newElementName)); element.Remove(); @@ -2532,7 +2550,7 @@ namespace WixToolset.Converters DefiningStandardDirectoryDeprecated, /// - /// Naked custom action and property references replaced with elements. + /// Naked UI, custom action, and property references replaced with elements. /// ReferencesReplaced, diff --git a/src/wix/test/WixToolsetTest.Converters/UIExtensionFixture.cs b/src/wix/test/WixToolsetTest.Converters/UIExtensionFixture.cs new file mode 100644 index 00000000..5f3809d4 --- /dev/null +++ b/src/wix/test/WixToolsetTest.Converters/UIExtensionFixture.cs @@ -0,0 +1,59 @@ +// 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. + +namespace WixToolsetTest.Converters +{ + using System; + using System.Xml.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Converters; + using WixToolsetTest.Converters.Mocks; + using Xunit; + + public class UIExtensionFixture : BaseConverterFixture + { + [Fact] + public void FixUIRefs() + { + var parse = String.Join(Environment.NewLine, + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + ""); + + var expected = new[] + { + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "" + }; + + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo); + + var messaging = new MockMessaging(); + var converter = new WixConverter(messaging, 2, null, null); + + var errors = converter.ConvertDocument(document); + Assert.Equal(7, errors); + + var actualLines = UnformattedDocumentLines(document); + WixAssert.CompareLineByLine(expected, actualLines); + } + } +} -- cgit v1.2.3-55-g6feb