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
)