From abfe02f2e31480f2cfb72b3daa641d7e723448d9 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Sat, 16 May 2020 21:53:44 +1000 Subject: WIXFEAT:6164 Implement DisplayInternalUICondition. --- src/test/WixToolsetTest.Bal/BalExtensionFixture.cs | 35 +++++++++++++ .../TestData/WixStdBa/Data/test.msi | Bin 0 -> 32768 bytes .../WixStdBa/DisplayInternalUIConditionBundle.wxs | 12 +++++ .../WixToolsetTest.Bal/WixToolsetTest.Bal.csproj | 2 + src/wixext/BalCompiler.cs | 17 +++++++ src/wixext/Tuples/BalTupleDefinitions.cs | 5 ++ src/wixext/Tuples/WixBalPackageInfoTuple.cs | 55 +++++++++++++++++++++ src/wixext/bal.xsd | 15 ++++++ .../WixStandardBootstrapperApplication.cpp | 47 ++++++++++++++++++ 9 files changed, 188 insertions(+) create mode 100644 src/test/WixToolsetTest.Bal/TestData/WixStdBa/Data/test.msi create mode 100644 src/test/WixToolsetTest.Bal/TestData/WixStdBa/DisplayInternalUIConditionBundle.wxs create mode 100644 src/wixext/Tuples/WixBalPackageInfoTuple.cs (limited to 'src') diff --git a/src/test/WixToolsetTest.Bal/BalExtensionFixture.cs b/src/test/WixToolsetTest.Bal/BalExtensionFixture.cs index 18b4727f..5780ca08 100644 --- a/src/test/WixToolsetTest.Bal/BalExtensionFixture.cs +++ b/src/test/WixToolsetTest.Bal/BalExtensionFixture.cs @@ -4,12 +4,47 @@ namespace WixToolsetTest.Bal { using System.IO; using System.Linq; + using System.Xml; using WixBuildTools.TestSupport; using WixToolset.Core.TestPackage; using Xunit; public class BalExtensionFixture { + [Fact] + public void CanBuildUsingDisplayInternalUICondition() + { + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(); + var bundleFile = Path.Combine(baseFolder, "bin", "test.exe"); + var bundleSourceFolder = TestData.Get(@"TestData\WixStdBa"); + var intermediateFolder = Path.Combine(baseFolder, "obj"); + var baFolderPath = Path.Combine(baseFolder, "ba"); + var extractFolderPath = Path.Combine(baseFolder, "extract"); + + var compileResult = WixRunner.Execute(new[] + { + "build", + Path.Combine(bundleSourceFolder, "DisplayInternalUIConditionBundle.wxs"), + "-ext", TestData.Get(@"WixToolset.Bal.wixext.dll"), + "-intermediateFolder", intermediateFolder, + "-bindpath", Path.Combine(bundleSourceFolder, "data"), + "-o", bundleFile, + }); + compileResult.AssertSuccess(); + + Assert.True(File.Exists(bundleFile)); + + var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath); + extractResult.AssertSuccess(); + + var balPackageInfos = extractResult.SelectBADataNodes("/ba:BootstrapperApplicationData/ba:WixBalPackageInfo"); + var balPackageInfo = (XmlNode)Assert.Single(balPackageInfos); + Assert.Equal("", balPackageInfo.GetTestXml()); + } + } + [Fact] public void CanBuildUsingWixStdBa() { diff --git a/src/test/WixToolsetTest.Bal/TestData/WixStdBa/Data/test.msi b/src/test/WixToolsetTest.Bal/TestData/WixStdBa/Data/test.msi new file mode 100644 index 00000000..94aacd1a Binary files /dev/null and b/src/test/WixToolsetTest.Bal/TestData/WixStdBa/Data/test.msi differ diff --git a/src/test/WixToolsetTest.Bal/TestData/WixStdBa/DisplayInternalUIConditionBundle.wxs b/src/test/WixToolsetTest.Bal/TestData/WixStdBa/DisplayInternalUIConditionBundle.wxs new file mode 100644 index 00000000..438fc23e --- /dev/null +++ b/src/test/WixToolsetTest.Bal/TestData/WixStdBa/DisplayInternalUIConditionBundle.wxs @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/src/test/WixToolsetTest.Bal/WixToolsetTest.Bal.csproj b/src/test/WixToolsetTest.Bal/WixToolsetTest.Bal.csproj index f970c2c8..f09a19a2 100644 --- a/src/test/WixToolsetTest.Bal/WixToolsetTest.Bal.csproj +++ b/src/test/WixToolsetTest.Bal/WixToolsetTest.Bal.csproj @@ -14,6 +14,8 @@ + + diff --git a/src/wixext/BalCompiler.cs b/src/wixext/BalCompiler.cs index dfe29bde..03b74e57 100644 --- a/src/wixext/BalCompiler.cs +++ b/src/wixext/BalCompiler.cs @@ -104,6 +104,23 @@ namespace WixToolset.Bal { switch (attribute.Name.LocalName) { + case "DisplayInternalUICondition": + switch (parentElement.Name.LocalName) + { + case "MsiPackage": + case "MspPackage": + var displayInternalUICondition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attribute); + section.AddTuple(new WixBalPackageInfoTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, packageId)) + { + PackageId = packageId, + DisplayInternalUICondition = displayInternalUICondition, + }); + break; + default: + this.ParseHelper.UnexpectedAttribute(parentElement, attribute); + break; + } + break; case "PrereqLicenseFile": if (!this.prereqInfoTuplesByPackageId.TryGetValue(packageId, out prereqInfo)) diff --git a/src/wixext/Tuples/BalTupleDefinitions.cs b/src/wixext/Tuples/BalTupleDefinitions.cs index 9a294703..08e7ba2a 100644 --- a/src/wixext/Tuples/BalTupleDefinitions.cs +++ b/src/wixext/Tuples/BalTupleDefinitions.cs @@ -11,6 +11,7 @@ namespace WixToolset.Bal WixBalBAFactoryAssembly, WixBalBAFunctions, WixBalCondition, + WixBalPackageInfo, WixDncOptions, WixMbaPrereqInformation, WixStdbaOptions, @@ -44,6 +45,9 @@ namespace WixToolset.Bal case BalTupleDefinitionType.WixBalCondition: return BalTupleDefinitions.WixBalCondition; + case BalTupleDefinitionType.WixBalPackageInfo: + return BalTupleDefinitions.WixBalPackageInfo; + case BalTupleDefinitionType.WixDncOptions: return BalTupleDefinitions.WixDncOptions; @@ -66,6 +70,7 @@ namespace WixToolset.Bal WixBalBAFactoryAssembly.AddTag(BurnConstants.BootstrapperApplicationDataTupleDefinitionTag); WixBalBAFunctions.AddTag(BurnConstants.BootstrapperApplicationDataTupleDefinitionTag); WixBalCondition.AddTag(BurnConstants.BootstrapperApplicationDataTupleDefinitionTag); + WixBalPackageInfo.AddTag(BurnConstants.BootstrapperApplicationDataTupleDefinitionTag); WixDncOptions.AddTag(BurnConstants.BootstrapperApplicationDataTupleDefinitionTag); WixMbaPrereqInformation.AddTag(BurnConstants.BootstrapperApplicationDataTupleDefinitionTag); WixStdbaOptions.AddTag(BurnConstants.BootstrapperApplicationDataTupleDefinitionTag); diff --git a/src/wixext/Tuples/WixBalPackageInfoTuple.cs b/src/wixext/Tuples/WixBalPackageInfoTuple.cs new file mode 100644 index 00000000..32be3105 --- /dev/null +++ b/src/wixext/Tuples/WixBalPackageInfoTuple.cs @@ -0,0 +1,55 @@ +// 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.Bal +{ + using WixToolset.Data; + using WixToolset.Bal.Tuples; + + public static partial class BalTupleDefinitions + { + public static readonly IntermediateTupleDefinition WixBalPackageInfo = new IntermediateTupleDefinition( + BalTupleDefinitionType.WixBalPackageInfo.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(WixBalPackageInfoTupleFields.PackageId), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBalPackageInfoTupleFields.DisplayInternalUICondition), IntermediateFieldType.String), + }, + typeof(WixBalPackageInfoTuple)); + } +} + +namespace WixToolset.Bal.Tuples +{ + using WixToolset.Data; + + public enum WixBalPackageInfoTupleFields + { + PackageId, + DisplayInternalUICondition, + } + + public class WixBalPackageInfoTuple : IntermediateTuple + { + public WixBalPackageInfoTuple() : base(BalTupleDefinitions.WixBalPackageInfo, null, null) + { + } + + public WixBalPackageInfoTuple(SourceLineNumber sourceLineNumber, Identifier id = null) : base(BalTupleDefinitions.WixBalPackageInfo, sourceLineNumber, id) + { + } + + public IntermediateField this[WixBalPackageInfoTupleFields index] => this.Fields[(int)index]; + + public string PackageId + { + get => this.Fields[(int)WixBalPackageInfoTupleFields.PackageId].AsString(); + set => this.Set((int)WixBalPackageInfoTupleFields.PackageId, value); + } + + public string DisplayInternalUICondition + { + get => this.Fields[(int)WixBalPackageInfoTupleFields.DisplayInternalUICondition].AsString(); + set => this.Set((int)WixBalPackageInfoTupleFields.DisplayInternalUICondition, value); + } + } +} diff --git a/src/wixext/bal.xsd b/src/wixext/bal.xsd index ee1f8cec..1bec2873 100644 --- a/src/wixext/bal.xsd +++ b/src/wixext/bal.xsd @@ -277,6 +277,21 @@ + + + + Specifies whether the bundle will show the UI authored into the msi package. If not specified or the condition evaluates + to false, all information is routed to the bootstrapper application to provide a unified installation experience. + Otherwise, the UI authored into the msi package will be displayed on top of any bootstrapper application UI. + WixStdBA doesn't support EmbeddedUI. + + + + + + + + diff --git a/src/wixstdba/WixStandardBootstrapperApplication.cpp b/src/wixstdba/WixStandardBootstrapperApplication.cpp index 69913de2..dd7ad229 100644 --- a/src/wixstdba/WixStandardBootstrapperApplication.cpp +++ b/src/wixstdba/WixStandardBootstrapperApplication.cpp @@ -456,6 +456,53 @@ public: // IBootstrapperApplication } + virtual STDMETHODIMP OnPlanMsiPackage( + __in_z LPCWSTR wzPackageId, + __in BOOL fExecute, + __in BOOTSTRAPPER_ACTION_STATE action, + __inout BOOL* pfCancel, + __inout BURN_MSI_PROPERTY* pActionMsiProperty, + __inout INSTALLUILEVEL* pUiLevel, + __inout BOOL* pfDisableExternalUiHandler + ) + { + HRESULT hr = S_OK; + WIXSTDBA_PACKAGE_INFO* pPackageInfo = NULL; + BAL_INFO_PACKAGE* pPackage = NULL; + BOOL fShowInternalUI = FALSE; + INSTALLUILEVEL uiLevel = INSTALLUILEVEL_NOCHANGE; + + switch (m_command.display) + { + case BOOTSTRAPPER_DISPLAY_FULL: + uiLevel = INSTALLUILEVEL_FULL; + break; + + case BOOTSTRAPPER_DISPLAY_PASSIVE: + uiLevel = INSTALLUILEVEL_REDUCED; + break; + } + + if (INSTALLUILEVEL_NOCHANGE != uiLevel) + { + hr = GetPackageInfo(wzPackageId, &pPackageInfo, &pPackage); + if (SUCCEEDED(hr) && pPackage->sczDisplayInternalUICondition) + { + hr = BalEvaluateCondition(pPackage->sczDisplayInternalUICondition, &fShowInternalUI); + BalExitOnFailure(hr, "Failed to evaluate condition for package '%ls': %ls", wzPackageId, pPackage->sczDisplayInternalUICondition); + + if (fShowInternalUI) + { + *pUiLevel = uiLevel; + } + } + } + + LExit: + return __super::OnPlanMsiPackage(wzPackageId, fExecute, action, pfCancel, pActionMsiProperty, pUiLevel, pfDisableExternalUiHandler); + } + + virtual STDMETHODIMP OnPlanComplete( __in HRESULT hrStatus ) -- cgit v1.2.3-55-g6feb