@joebigelow / wix / commits / abfe02f2

WIXFEAT:6164 Implement DisplayInternalUICondition.

Sean Hall committed May 16, 2020 at 21:53 UTC abfe02f2e31480f2cfb72b3daa641d7e723448d9
9 files changed +188
src/test/WixToolsetTest.Bal/BalExtensionFixture.cs
+35
@@ -4,12 +4,47 @@ namespace WixToolsetTest.Bal
4 {
5 using System.IO;
6 using System.Linq;
7 + using System.Xml;
8 using WixBuildTools.TestSupport;
9 using WixToolset.Core.TestPackage;
10 using Xunit;
11
12 public class BalExtensionFixture
13 {
14 + [Fact]
15 + public void CanBuildUsingDisplayInternalUICondition()
16 + {
17 + using (var fs = new DisposableFileSystem())
18 + {
19 + var baseFolder = fs.GetFolder();
20 + var bundleFile = Path.Combine(baseFolder, "bin", "test.exe");
21 + var bundleSourceFolder = TestData.Get(@"TestData\WixStdBa");
22 + var intermediateFolder = Path.Combine(baseFolder, "obj");
23 + var baFolderPath = Path.Combine(baseFolder, "ba");
24 + var extractFolderPath = Path.Combine(baseFolder, "extract");
25 +
26 + var compileResult = WixRunner.Execute(new[]
27 + {
28 + "build",
29 + Path.Combine(bundleSourceFolder, "DisplayInternalUIConditionBundle.wxs"),
30 + "-ext", TestData.Get(@"WixToolset.Bal.wixext.dll"),
31 + "-intermediateFolder", intermediateFolder,
32 + "-bindpath", Path.Combine(bundleSourceFolder, "data"),
33 + "-o", bundleFile,
34 + });
35 + compileResult.AssertSuccess();
36 +
37 + Assert.True(File.Exists(bundleFile));
38 +
39 + var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath);
40 + extractResult.AssertSuccess();
41 +
42 + var balPackageInfos = extractResult.SelectBADataNodes("/ba:BootstrapperApplicationData/ba:WixBalPackageInfo");
43 + var balPackageInfo = (XmlNode)Assert.Single(balPackageInfos);
44 + Assert.Equal("<WixBalPackageInfo PackageId='test.msi' DisplayInternalUICondition='1' />", balPackageInfo.GetTestXml());
45 + }
46 + }
47 +
48 [Fact]
49 public void CanBuildUsingWixStdBa()
50 {
src/test/WixToolsetTest.Bal/TestData/WixStdBa/Data/test.msi
Binary files /dev/null and b/src/test/WixToolsetTest.Bal/TestData/WixStdBa/Data/test.msi differ
src/test/WixToolsetTest.Bal/TestData/WixStdBa/DisplayInternalUIConditionBundle.wxs new
+12
@@ -0,0 +1,12 @@
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3 + xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
4 + <Bundle Name="WixStdBa" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="75D5D534-E177-4689-AAE9-CAC1C39002C2">
5 + <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLicense">
6 + <bal:WixStandardBootstrapperApplication LicenseUrl="http://wixtoolset.org/about/license/" />
7 + </BootstrapperApplicationRef>
8 + <Chain>
9 + <MsiPackage SourceFile="test.msi" bal:DisplayInternalUICondition="1" />
10 + </Chain>
11 + </Bundle>
12 +</Wix>
src/test/WixToolsetTest.Bal/WixToolsetTest.Bal.csproj
+2
@@ -14,6 +14,8 @@
14 <ItemGroup>
15 <Content Include="TestData\MBA\Bundle.wxs" CopyToOutputDirectory="PreserveNewest" />
16 <Content Include="TestData\WixStdBa\Bundle.wxs" CopyToOutputDirectory="PreserveNewest" />
17 + <Content Include="TestData\WixStdBa\Data\test.msi" CopyToOutputDirectory="PreserveNewest" />
18 + <Content Include="TestData\WixStdBa\DisplayInternalUIConditionBundle.wxs" CopyToOutputDirectory="PreserveNewest" />
19 </ItemGroup>
20
21 <Target Name="CopyExtensions" AfterTargets="Build">
src/wixext/BalCompiler.cs
+17
@@ -104,6 +104,23 @@ namespace WixToolset.Bal
104 {
105 switch (attribute.Name.LocalName)
106 {
107 + case "DisplayInternalUICondition":
108 + switch (parentElement.Name.LocalName)
109 + {
110 + case "MsiPackage":
111 + case "MspPackage":
112 + var displayInternalUICondition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attribute);
113 + section.AddTuple(new WixBalPackageInfoTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, packageId))
114 + {
115 + PackageId = packageId,
116 + DisplayInternalUICondition = displayInternalUICondition,
117 + });
118 + break;
119 + default:
120 + this.ParseHelper.UnexpectedAttribute(parentElement, attribute);
121 + break;
122 + }
123 + break;
124 case "PrereqLicenseFile":
125
126 if (!this.prereqInfoTuplesByPackageId.TryGetValue(packageId, out prereqInfo))
src/wixext/Tuples/BalTupleDefinitions.cs
+5
@@ -11,6 +11,7 @@ namespace WixToolset.Bal
11 WixBalBAFactoryAssembly,
12 WixBalBAFunctions,
13 WixBalCondition,
14 + WixBalPackageInfo,
15 WixDncOptions,
16 WixMbaPrereqInformation,
17 WixStdbaOptions,
@@ -44,6 +45,9 @@ namespace WixToolset.Bal
45 case BalTupleDefinitionType.WixBalCondition:
46 return BalTupleDefinitions.WixBalCondition;
47
48 + case BalTupleDefinitionType.WixBalPackageInfo:
49 + return BalTupleDefinitions.WixBalPackageInfo;
50 +
51 case BalTupleDefinitionType.WixDncOptions:
52 return BalTupleDefinitions.WixDncOptions;
53
@@ -66,6 +70,7 @@ namespace WixToolset.Bal
70 WixBalBAFactoryAssembly.AddTag(BurnConstants.BootstrapperApplicationDataTupleDefinitionTag);
71 WixBalBAFunctions.AddTag(BurnConstants.BootstrapperApplicationDataTupleDefinitionTag);
72 WixBalCondition.AddTag(BurnConstants.BootstrapperApplicationDataTupleDefinitionTag);
73 + WixBalPackageInfo.AddTag(BurnConstants.BootstrapperApplicationDataTupleDefinitionTag);
74 WixDncOptions.AddTag(BurnConstants.BootstrapperApplicationDataTupleDefinitionTag);
75 WixMbaPrereqInformation.AddTag(BurnConstants.BootstrapperApplicationDataTupleDefinitionTag);
76 WixStdbaOptions.AddTag(BurnConstants.BootstrapperApplicationDataTupleDefinitionTag);
src/wixext/Tuples/WixBalPackageInfoTuple.cs new
+55
@@ -0,0 +1,55 @@
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 WixToolset.Bal
4 +{
5 + using WixToolset.Data;
6 + using WixToolset.Bal.Tuples;
7 +
8 + public static partial class BalTupleDefinitions
9 + {
10 + public static readonly IntermediateTupleDefinition WixBalPackageInfo = new IntermediateTupleDefinition(
11 + BalTupleDefinitionType.WixBalPackageInfo.ToString(),
12 + new[]
13 + {
14 + new IntermediateFieldDefinition(nameof(WixBalPackageInfoTupleFields.PackageId), IntermediateFieldType.String),
15 + new IntermediateFieldDefinition(nameof(WixBalPackageInfoTupleFields.DisplayInternalUICondition), IntermediateFieldType.String),
16 + },
17 + typeof(WixBalPackageInfoTuple));
18 + }
19 +}
20 +
21 +namespace WixToolset.Bal.Tuples
22 +{
23 + using WixToolset.Data;
24 +
25 + public enum WixBalPackageInfoTupleFields
26 + {
27 + PackageId,
28 + DisplayInternalUICondition,
29 + }
30 +
31 + public class WixBalPackageInfoTuple : IntermediateTuple
32 + {
33 + public WixBalPackageInfoTuple() : base(BalTupleDefinitions.WixBalPackageInfo, null, null)
34 + {
35 + }
36 +
37 + public WixBalPackageInfoTuple(SourceLineNumber sourceLineNumber, Identifier id = null) : base(BalTupleDefinitions.WixBalPackageInfo, sourceLineNumber, id)
38 + {
39 + }
40 +
41 + public IntermediateField this[WixBalPackageInfoTupleFields index] => this.Fields[(int)index];
42 +
43 + public string PackageId
44 + {
45 + get => this.Fields[(int)WixBalPackageInfoTupleFields.PackageId].AsString();
46 + set => this.Set((int)WixBalPackageInfoTupleFields.PackageId, value);
47 + }
48 +
49 + public string DisplayInternalUICondition
50 + {
51 + get => this.Fields[(int)WixBalPackageInfoTupleFields.DisplayInternalUICondition].AsString();
52 + set => this.Set((int)WixBalPackageInfoTupleFields.DisplayInternalUICondition, value);
53 + }
54 + }
55 +}
src/wixext/bal.xsd
+15
@@ -277,6 +277,21 @@
277 </xs:annotation>
278 </xs:attribute>
279
280 + <xs:attribute name="DisplayInternalUICondition" type="xs:string">
281 + <xs:annotation>
282 + <xs:documentation>
283 + Specifies whether the bundle will show the UI authored into the msi package. If not specified or the condition evaluates
284 + to false, all information is routed to the bootstrapper application to provide a unified installation experience.
285 + Otherwise, the UI authored into the msi package will be displayed on top of any bootstrapper application UI.
286 + WixStdBA doesn't support EmbeddedUI.
287 + </xs:documentation>
288 + <xs:appinfo>
289 + <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="MsiPackage" />
290 + <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="MspPackage" />
291 + </xs:appinfo>
292 + </xs:annotation>
293 + </xs:attribute>
294 +
295 <xs:attribute name="Overridable" type="YesNoType">
296 <xs:annotation>
297 <xs:documentation>
src/wixstdba/WixStandardBootstrapperApplication.cpp
+47
@@ -456,6 +456,53 @@ public: // IBootstrapperApplication
456 }
457
458
459 + virtual STDMETHODIMP OnPlanMsiPackage(
460 + __in_z LPCWSTR wzPackageId,
461 + __in BOOL fExecute,
462 + __in BOOTSTRAPPER_ACTION_STATE action,
463 + __inout BOOL* pfCancel,
464 + __inout BURN_MSI_PROPERTY* pActionMsiProperty,
465 + __inout INSTALLUILEVEL* pUiLevel,
466 + __inout BOOL* pfDisableExternalUiHandler
467 + )
468 + {
469 + HRESULT hr = S_OK;
470 + WIXSTDBA_PACKAGE_INFO* pPackageInfo = NULL;
471 + BAL_INFO_PACKAGE* pPackage = NULL;
472 + BOOL fShowInternalUI = FALSE;
473 + INSTALLUILEVEL uiLevel = INSTALLUILEVEL_NOCHANGE;
474 +
475 + switch (m_command.display)
476 + {
477 + case BOOTSTRAPPER_DISPLAY_FULL:
478 + uiLevel = INSTALLUILEVEL_FULL;
479 + break;
480 +
481 + case BOOTSTRAPPER_DISPLAY_PASSIVE:
482 + uiLevel = INSTALLUILEVEL_REDUCED;
483 + break;
484 + }
485 +
486 + if (INSTALLUILEVEL_NOCHANGE != uiLevel)
487 + {
488 + hr = GetPackageInfo(wzPackageId, &pPackageInfo, &pPackage);
489 + if (SUCCEEDED(hr) && pPackage->sczDisplayInternalUICondition)
490 + {
491 + hr = BalEvaluateCondition(pPackage->sczDisplayInternalUICondition, &fShowInternalUI);
492 + BalExitOnFailure(hr, "Failed to evaluate condition for package '%ls': %ls", wzPackageId, pPackage->sczDisplayInternalUICondition);
493 +
494 + if (fShowInternalUI)
495 + {
496 + *pUiLevel = uiLevel;
497 + }
498 + }
499 + }
500 +
501 + LExit:
502 + return __super::OnPlanMsiPackage(wzPackageId, fExecute, action, pfCancel, pActionMsiProperty, pUiLevel, pfDisableExternalUiHandler);
503 + }
504 +
505 +
506 virtual STDMETHODIMP OnPlanComplete(
507 __in HRESULT hrStatus
508 )