aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-04-04 17:38:26 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-04-05 13:52:11 -0500
commit75f4dce4ea53b82f99932573f27ccfc799d0c5c1 (patch)
tree4225579b861b4998138c19e9108d3cf91b13ad80 /src
parent44c2ca035c1a5d52a6b3299ba3abbb8b88f7f1c0 (diff)
downloadwix-75f4dce4ea53b82f99932573f27ccfc799d0c5c1.tar.gz
wix-75f4dce4ea53b82f99932573f27ccfc799d0c5c1.tar.bz2
wix-75f4dce4ea53b82f99932573f27ccfc799d0c5c1.zip
Add option for BundlePackage to be hidden in ARP like MsiPackage.
Requires support for this feature in the nested bundle. Simplest implementation of 4454
Diffstat (limited to 'src')
-rw-r--r--src/burn/engine/bundlepackageengine.cpp10
-rw-r--r--src/burn/engine/core.cpp29
-rw-r--r--src/burn/engine/core.h2
-rw-r--r--src/burn/engine/logging.cpp8
-rw-r--r--src/burn/engine/package.h1
-rw-r--r--src/burn/engine/plan.cpp5
-rw-r--r--src/burn/engine/plan.h1
-rw-r--r--src/burn/engine/registration.cpp2
-rw-r--r--src/burn/test/BurnUnitTest/PlanTest.cpp4
-rw-r--r--src/test/burn/TestData/BundlePackageTests/V3BundlePackageBundle/V3BundlePackageBundle.wixproj1
-rw-r--r--src/test/burn/WixTestTools/BundleRegistration.cs3
-rw-r--r--src/test/burn/WixTestTools/BundleVerifier.cs4
-rw-r--r--src/test/burn/WixToolsetTest.BurnE2E/BundlePackageTests.cs50
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/BurnCommon.cs1
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs5
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs7
-rw-r--r--src/wix/WixToolset.Core.Burn/BurnBackendWarnings.cs6
-rw-r--r--src/wix/WixToolset.Core/Compiler_Bundle.cs11
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs97
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/TestData/BundlePackage/BundlePackage.wxs2
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/TestData/BundlePackage/PermanentBundlePackage.wxs10
21 files changed, 243 insertions, 16 deletions
diff --git a/src/burn/engine/bundlepackageengine.cpp b/src/burn/engine/bundlepackageengine.cpp
index cb34878f..00cf9454 100644
--- a/src/burn/engine/bundlepackageengine.cpp
+++ b/src/burn/engine/bundlepackageengine.cpp
@@ -72,6 +72,10 @@ extern "C" HRESULT BundlePackageEngineParsePackageFromXml(
72 hr = XmlGetAttributeEx(pixnBundlePackage, L"RepairArguments", &pPackage->Bundle.sczRepairArguments); 72 hr = XmlGetAttributeEx(pixnBundlePackage, L"RepairArguments", &pPackage->Bundle.sczRepairArguments);
73 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @RepairArguments."); 73 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @RepairArguments.");
74 74
75 // @HideARP
76 hr = XmlGetYesNoAttribute(pixnBundlePackage, L"HideARP", &pPackage->Bundle.fHideARP);
77 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @HideARP.");
78
75 // @SupportsBurnProtocol 79 // @SupportsBurnProtocol
76 hr = XmlGetYesNoAttribute(pixnBundlePackage, L"SupportsBurnProtocol", &pPackage->Bundle.fSupportsBurnProtocol); 80 hr = XmlGetYesNoAttribute(pixnBundlePackage, L"SupportsBurnProtocol", &pPackage->Bundle.fSupportsBurnProtocol);
77 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @SupportsBurnProtocol."); 81 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @SupportsBurnProtocol.");
@@ -870,6 +874,12 @@ static HRESULT ExecuteBundle(
870 ExitOnFailure(hr, "Failed to append the parent to the command line."); 874 ExitOnFailure(hr, "Failed to append the parent to the command line.");
871 } 875 }
872 876
877 if (pPackage->Bundle.fHideARP)
878 {
879 hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls", BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT);
880 ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT);
881 }
882
873 // Add the list of dependencies to ignore, if any, to the burn command line. 883 // Add the list of dependencies to ignore, if any, to the burn command line.
874 if (BOOTSTRAPPER_RELATION_CHAIN_PACKAGE == relationType) 884 if (BOOTSTRAPPER_RELATION_CHAIN_PACKAGE == relationType)
875 { 885 {
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index 0bbf7039..be8c011f 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -1044,6 +1044,12 @@ static HRESULT CoreRecreateCommandLine(
1044 ExitOnFailure(hr, "Failed to append relation type to command-line."); 1044 ExitOnFailure(hr, "Failed to append relation type to command-line.");
1045 } 1045 }
1046 1046
1047 if (pInternalCommand->fArpSystemComponent)
1048 {
1049 hr = StrAllocConcatFormatted(psczCommandLine, L" /%ls", BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT);
1050 ExitOnFailure(hr, "Failed to append system component to command-line.");
1051 }
1052
1047 if (fPassthrough) 1053 if (fPassthrough)
1048 { 1054 {
1049 hr = StrAllocConcatFormatted(psczCommandLine, L" /%ls", BURN_COMMANDLINE_SWITCH_PASSTHROUGH); 1055 hr = StrAllocConcatFormatted(psczCommandLine, L" /%ls", BURN_COMMANDLINE_SWITCH_PASSTHROUGH);
@@ -1633,6 +1639,29 @@ extern "C" HRESULT CoreParseCommandLine(
1633 } 1639 }
1634 } 1640 }
1635 } 1641 }
1642 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], lstrlenW(BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT), BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT, lstrlenW(BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT)))
1643 {
1644 // Get a pointer to the next character after the switch.
1645 LPCWSTR wzParam = &argv[i][1 + lstrlenW(BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT)];
1646
1647 // Switch without an argument is allowed. An empty string means FALSE, everything else means TRUE.
1648 if (L'\0' != wzParam[0])
1649 {
1650 if (L'=' != wzParam[0])
1651 {
1652 fInvalidCommandLine = TRUE;
1653 TraceLog(E_INVALIDARG, "Invalid switch: %ls", argv[i]);
1654 }
1655 else
1656 {
1657 pInternalCommand->fArpSystemComponent = L'\0' != wzParam[1];
1658 }
1659 }
1660 else
1661 {
1662 pInternalCommand->fArpSystemComponent = TRUE;
1663 }
1664 }
1636 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_EMBEDDED, -1)) 1665 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_EMBEDDED, -1))
1637 { 1666 {
1638 if (i + 3 >= argc) 1667 if (i + 3 >= argc)
diff --git a/src/burn/engine/core.h b/src/burn/engine/core.h
index 556124d6..c04de20a 100644
--- a/src/burn/engine/core.h
+++ b/src/burn/engine/core.h
@@ -35,6 +35,7 @@ const LPCWSTR BURN_COMMANDLINE_SWITCH_ANCESTORS = L"burn.ancestors";
35const LPCWSTR BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED = L"burn.filehandle.attached"; 35const LPCWSTR BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED = L"burn.filehandle.attached";
36const LPCWSTR BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF = L"burn.filehandle.self"; 36const LPCWSTR BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF = L"burn.filehandle.self";
37const LPCWSTR BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN = L"burn.splash.screen"; 37const LPCWSTR BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN = L"burn.splash.screen";
38const LPCWSTR BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT = L"burn.system.component";
38const LPCWSTR BURN_COMMANDLINE_SWITCH_PREFIX = L"burn."; 39const LPCWSTR BURN_COMMANDLINE_SWITCH_PREFIX = L"burn.";
39 40
40const LPCWSTR BURN_BUNDLE_LAYOUT_DIRECTORY = L"WixBundleLayoutDirectory"; 41const LPCWSTR BURN_BUNDLE_LAYOUT_DIRECTORY = L"WixBundleLayoutDirectory";
@@ -95,6 +96,7 @@ typedef struct _BURN_ENGINE_COMMAND
95 96
96 BURN_MODE mode; 97 BURN_MODE mode;
97 BURN_AU_PAUSE_ACTION automaticUpdates; 98 BURN_AU_PAUSE_ACTION automaticUpdates;
99 BOOL fArpSystemComponent;
98 BOOL fDisableSystemRestore; 100 BOOL fDisableSystemRestore;
99 BOOL fInitiallyElevated; 101 BOOL fInitiallyElevated;
100 102
diff --git a/src/burn/engine/logging.cpp b/src/burn/engine/logging.cpp
index a766b896..0b510f3d 100644
--- a/src/burn/engine/logging.cpp
+++ b/src/burn/engine/logging.cpp
@@ -752,8 +752,16 @@ extern "C" LPCSTR LoggingRegistrationOptionsToString(
752 return "CacheBundle"; 752 return "CacheBundle";
753 case BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_PROVIDER_KEY: 753 case BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_PROVIDER_KEY:
754 return "WriteProviderKey"; 754 return "WriteProviderKey";
755 case BURN_REGISTRATION_ACTION_OPERATIONS_ARP_SYSTEM_COMPONENT:
756 return "ArpSystemComponent";
755 case BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE + BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_PROVIDER_KEY: 757 case BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE + BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_PROVIDER_KEY:
756 return "CacheBundle, WriteProviderKey"; 758 return "CacheBundle, WriteProviderKey";
759 case BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE + BURN_REGISTRATION_ACTION_OPERATIONS_ARP_SYSTEM_COMPONENT:
760 return "CacheBundle, ArpSystemComponent";
761 case BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_PROVIDER_KEY + BURN_REGISTRATION_ACTION_OPERATIONS_ARP_SYSTEM_COMPONENT:
762 return "WriteProviderKey, ArpSystemComponent";
763 case BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE + BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_PROVIDER_KEY + BURN_REGISTRATION_ACTION_OPERATIONS_ARP_SYSTEM_COMPONENT:
764 return "CacheBundle, WriteProviderKey, ArpSystemComponent";
757 default: 765 default:
758 return "Invalid"; 766 return "Invalid";
759 } 767 }
diff --git a/src/burn/engine/package.h b/src/burn/engine/package.h
index 4021031f..eb8e7543 100644
--- a/src/burn/engine/package.h
+++ b/src/burn/engine/package.h
@@ -321,6 +321,7 @@ typedef struct _BURN_PACKAGE
321 LPWSTR* rgsczPatchCodes; 321 LPWSTR* rgsczPatchCodes;
322 DWORD cPatchCodes; 322 DWORD cPatchCodes;
323 323
324 BOOL fHideARP;
324 BOOL fWin64; 325 BOOL fWin64;
325 BOOL fSupportsBurnProtocol; 326 BOOL fSupportsBurnProtocol;
326 327
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp
index 183ac62a..2c267415 100644
--- a/src/burn/engine/plan.cpp
+++ b/src/burn/engine/plan.cpp
@@ -581,6 +581,11 @@ extern "C" HRESULT PlanRegistration(
581 pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE; 581 pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE;
582 } 582 }
583 583
584 if (pPlan->pInternalCommand->fArpSystemComponent)
585 {
586 pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_ARP_SYSTEM_COMPONENT;
587 }
588
584 if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pPlan->action) 589 if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pPlan->action)
585 { 590 {
586 // If our provider key was not owned by a different bundle, 591 // If our provider key was not owned by a different bundle,
diff --git a/src/burn/engine/plan.h b/src/burn/engine/plan.h
index a8b16705..87214cc8 100644
--- a/src/burn/engine/plan.h
+++ b/src/burn/engine/plan.h
@@ -16,6 +16,7 @@ enum BURN_REGISTRATION_ACTION_OPERATIONS
16 BURN_REGISTRATION_ACTION_OPERATIONS_NONE = 0x0, 16 BURN_REGISTRATION_ACTION_OPERATIONS_NONE = 0x0,
17 BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE = 0x1, 17 BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE = 0x1,
18 BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_PROVIDER_KEY = 0x2, 18 BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_PROVIDER_KEY = 0x2,
19 BURN_REGISTRATION_ACTION_OPERATIONS_ARP_SYSTEM_COMPONENT = 0x4,
19}; 20};
20 21
21enum BURN_DEPENDENT_REGISTRATION_ACTION_TYPE 22enum BURN_DEPENDENT_REGISTRATION_ACTION_TYPE
diff --git a/src/burn/engine/registration.cpp b/src/burn/engine/registration.cpp
index 961e86bc..0ffbc89e 100644
--- a/src/burn/engine/registration.cpp
+++ b/src/burn/engine/registration.cpp
@@ -767,7 +767,7 @@ extern "C" HRESULT RegistrationSessionBegin(
767 } 767 }
768 768
769 // Conditionally hide the ARP entry. 769 // Conditionally hide the ARP entry.
770 if (pRegistration->fForceSystemComponent) 770 if (pRegistration->fForceSystemComponent || (dwRegistrationOptions & BURN_REGISTRATION_ACTION_OPERATIONS_ARP_SYSTEM_COMPONENT))
771 { 771 {
772 hr = RegWriteNumber(hkRegistration, REGISTRY_BUNDLE_SYSTEM_COMPONENT, 1); 772 hr = RegWriteNumber(hkRegistration, REGISTRY_BUNDLE_SYSTEM_COMPONENT, 1);
773 ExitOnFailure(hr, "Failed to write %ls value.", REGISTRY_BUNDLE_SYSTEM_COMPONENT); 773 ExitOnFailure(hr, "Failed to write %ls value.", REGISTRY_BUNDLE_SYSTEM_COMPONENT);
diff --git a/src/burn/test/BurnUnitTest/PlanTest.cpp b/src/burn/test/BurnUnitTest/PlanTest.cpp
index 26e7dfd2..87bbbffd 100644
--- a/src/burn/test/BurnUnitTest/PlanTest.cpp
+++ b/src/burn/test/BurnUnitTest/PlanTest.cpp
@@ -1232,6 +1232,8 @@ namespace Bootstrapper
1232 BURN_ENGINE_STATE* pEngineState = &engineState; 1232 BURN_ENGINE_STATE* pEngineState = &engineState;
1233 BURN_PLAN* pPlan = &engineState.plan; 1233 BURN_PLAN* pPlan = &engineState.plan;
1234 1234
1235 pEngineState->internalCommand.fArpSystemComponent = TRUE;
1236
1235 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState); 1237 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState);
1236 DetectAttachedContainerAsAttached(pEngineState); 1238 DetectAttachedContainerAsAttached(pEngineState);
1237 DetectPackagesAsAbsent(pEngineState); 1239 DetectPackagesAsAbsent(pEngineState);
@@ -1249,7 +1251,7 @@ namespace Bootstrapper
1249 Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback); 1251 Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
1250 Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval); 1252 Assert::Equal<BOOL>(FALSE, pPlan->fDisallowRemoval);
1251 Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade); 1253 Assert::Equal<BOOL>(FALSE, pPlan->fDowngrade);
1252 Assert::Equal<DWORD>(BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE | BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_PROVIDER_KEY, pPlan->dwRegistrationOperations); 1254 Assert::Equal<DWORD>(BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE | BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_PROVIDER_KEY | BURN_REGISTRATION_ACTION_OPERATIONS_ARP_SYSTEM_COMPONENT, pPlan->dwRegistrationOperations);
1253 1255
1254 BOOL fRollback = FALSE; 1256 BOOL fRollback = FALSE;
1255 DWORD dwIndex = 0; 1257 DWORD dwIndex = 0;
diff --git a/src/test/burn/TestData/BundlePackageTests/V3BundlePackageBundle/V3BundlePackageBundle.wixproj b/src/test/burn/TestData/BundlePackageTests/V3BundlePackageBundle/V3BundlePackageBundle.wixproj
index d57ac072..a7930a09 100644
--- a/src/test/burn/TestData/BundlePackageTests/V3BundlePackageBundle/V3BundlePackageBundle.wixproj
+++ b/src/test/burn/TestData/BundlePackageTests/V3BundlePackageBundle/V3BundlePackageBundle.wixproj
@@ -5,6 +5,7 @@
5 <BA>TestBA_x64</BA> 5 <BA>TestBA_x64</BA>
6 <UpgradeCode>{B6CAE45D-A7E5-4302-9FCF-4D05632F9FD7}</UpgradeCode> 6 <UpgradeCode>{B6CAE45D-A7E5-4302-9FCF-4D05632F9FD7}</UpgradeCode>
7 <InstallerPlatform>x64</InstallerPlatform> 7 <InstallerPlatform>x64</InstallerPlatform>
8 <SuppressSpecificWarnings>8506</SuppressSpecificWarnings>
8 </PropertyGroup> 9 </PropertyGroup>
9 <ItemGroup> 10 <ItemGroup>
10 <Compile Include="..\..\Templates\Bundle.wxs" Link="Bundle.wxs" /> 11 <Compile Include="..\..\Templates\Bundle.wxs" Link="Bundle.wxs" />
diff --git a/src/test/burn/WixTestTools/BundleRegistration.cs b/src/test/burn/WixTestTools/BundleRegistration.cs
index 75660838..3541e7ea 100644
--- a/src/test/burn/WixTestTools/BundleRegistration.cs
+++ b/src/test/burn/WixTestTools/BundleRegistration.cs
@@ -66,6 +66,8 @@ namespace WixTestTools
66 66
67 public string Publisher { get; set; } 67 public string Publisher { get; set; }
68 68
69 public int? SystemComponent { get; set; }
70
69 public string QuietUninstallString { get; set; } 71 public string QuietUninstallString { get; set; }
70 72
71 public string QuietUninstallCommand { get; set; } 73 public string QuietUninstallCommand { get; set; }
@@ -125,6 +127,7 @@ namespace WixTestTools
125 registration.Installed = idKey.GetValue(REGISTRY_BUNDLE_INSTALLED) as int?; 127 registration.Installed = idKey.GetValue(REGISTRY_BUNDLE_INSTALLED) as int?;
126 registration.ModifyPath = idKey.GetValue(REGISTRY_BUNDLE_MODIFY_PATH) as string; 128 registration.ModifyPath = idKey.GetValue(REGISTRY_BUNDLE_MODIFY_PATH) as string;
127 registration.Publisher = idKey.GetValue(REGISTRY_BUNDLE_PUBLISHER) as string; 129 registration.Publisher = idKey.GetValue(REGISTRY_BUNDLE_PUBLISHER) as string;
130 registration.SystemComponent = idKey.GetValue(REGISTRY_BUNDLE_SYSTEM_COMPONENT) as int?;
128 registration.UrlInfoAbout = idKey.GetValue(REGISTRY_BUNDLE_URL_INFO_ABOUT) as string; 131 registration.UrlInfoAbout = idKey.GetValue(REGISTRY_BUNDLE_URL_INFO_ABOUT) as string;
129 registration.UrlUpdateInfo = idKey.GetValue(REGISTRY_BUNDLE_URL_UPDATE_INFO) as string; 132 registration.UrlUpdateInfo = idKey.GetValue(REGISTRY_BUNDLE_URL_UPDATE_INFO) as string;
130 133
diff --git a/src/test/burn/WixTestTools/BundleVerifier.cs b/src/test/burn/WixTestTools/BundleVerifier.cs
index e0edb081..a5dbe0ec 100644
--- a/src/test/burn/WixTestTools/BundleVerifier.cs
+++ b/src/test/burn/WixTestTools/BundleVerifier.cs
@@ -87,10 +87,12 @@ namespace WixTestTools
87 } 87 }
88 } 88 }
89 89
90 public string VerifyRegisteredAndInPackageCache() 90 public string VerifyRegisteredAndInPackageCache(int? expectedSystemComponent = null)
91 { 91 {
92 Assert.True(this.TryGetRegistration(out var registration)); 92 Assert.True(this.TryGetRegistration(out var registration));
93 93
94 Assert.Equal(expectedSystemComponent, registration.SystemComponent);
95
94 Assert.NotNull(registration.CachePath); 96 Assert.NotNull(registration.CachePath);
95 Assert.True(File.Exists(registration.CachePath)); 97 Assert.True(File.Exists(registration.CachePath));
96 98
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/BundlePackageTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/BundlePackageTests.cs
index 1bb0c0b6..bcdea974 100644
--- a/src/test/burn/WixToolsetTest.BurnE2E/BundlePackageTests.cs
+++ b/src/test/burn/WixToolsetTest.BurnE2E/BundlePackageTests.cs
@@ -31,8 +31,8 @@ namespace WixToolsetTest.BurnE2E
31 multipleBundlePackagesBundle.Install(); 31 multipleBundlePackagesBundle.Install();
32 multipleBundlePackagesBundle.VerifyRegisteredAndInPackageCache(); 32 multipleBundlePackagesBundle.VerifyRegisteredAndInPackageCache();
33 33
34 bundleA.VerifyRegisteredAndInPackageCache(); 34 bundleA.VerifyRegisteredAndInPackageCache(expectedSystemComponent: 1);
35 bundleB_x64.VerifyRegisteredAndInPackageCache(); 35 bundleB_x64.VerifyRegisteredAndInPackageCache(expectedSystemComponent: 1);
36 36
37 // Source file should be installed 37 // Source file should be installed
38 Assert.True(File.Exists(packageA32SourceCodeFilePath), $"Should have found PackageA payload installed at: {packageA32SourceCodeFilePath}"); 38 Assert.True(File.Exists(packageA32SourceCodeFilePath), $"Should have found PackageA payload installed at: {packageA32SourceCodeFilePath}");
@@ -61,14 +61,15 @@ namespace WixToolsetTest.BurnE2E
61 61
62 upgradeBundlePackageBundlev2.Install(); 62 upgradeBundlePackageBundlev2.Install();
63 upgradeBundlePackageBundlev2.VerifyRegisteredAndInPackageCache(); 63 upgradeBundlePackageBundlev2.VerifyRegisteredAndInPackageCache();
64 bundleAv2.VerifyRegisteredAndInPackageCache(); 64 bundleAv2.VerifyRegisteredAndInPackageCache(expectedSystemComponent: 1);
65 bundleAv1.VerifyUnregisteredAndRemovedFromPackageCache(); 65 bundleAv1.VerifyUnregisteredAndRemovedFromPackageCache();
66 } 66 }
67 67
68 [Fact] 68 [Fact]
69 public void CanInstallV3BundlePackage() 69 public void CanInstallV3BundlePackage()
70 { 70 {
71 var v3BundleName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Package Cache", "{215a70db-ab35-48c7-be51-d66eaac87177}", "CustomV3Theme"); 71 var v3BundleId = "{215a70db-ab35-48c7-be51-d66eaac87177}";
72 var v3BundleName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Package Cache", v3BundleId, "CustomV3Theme");
72 var v3Bundle = new BundleInstaller(this.TestContext, v3BundleName); 73 var v3Bundle = new BundleInstaller(this.TestContext, v3BundleName);
73 this.AddBundleInstaller(v3Bundle); 74 this.AddBundleInstaller(v3Bundle);
74 var v3BundlePackageBundle = this.CreateBundleInstaller("V3BundlePackageBundle"); 75 var v3BundlePackageBundle = this.CreateBundleInstaller("V3BundlePackageBundle");
@@ -79,6 +80,47 @@ namespace WixToolsetTest.BurnE2E
79 v3BundlePackageBundle.VerifyRegisteredAndInPackageCache(); 80 v3BundlePackageBundle.VerifyRegisteredAndInPackageCache();
80 81
81 Assert.True(LogVerifier.MessageInLogFile(logPath, "Applied execute package: v3bundle.exe, result: 0x0, restart: None")); 82 Assert.True(LogVerifier.MessageInLogFile(logPath, "Applied execute package: v3bundle.exe, result: 0x0, restart: None"));
83
84 Assert.True(BundleRegistration.TryGetPerMachineBundleRegistrationById(v3BundleId, false, out var v3Registration));
85 Assert.Null(v3Registration.SystemComponent);
86 }
87
88 [Fact]
89 public void CanLeaveBundlePackageVisible()
90 {
91 var bundleAv1 = this.CreateBundleInstaller(@"..\UpgradeRelatedBundleTests\BundleAv1");
92 var upgradeBundlePackageBundlev1 = this.CreateBundleInstaller("UpgradeBundlePackageBundlev1");
93
94 bundleAv1.Install();
95 bundleAv1.VerifyRegisteredAndInPackageCache();
96
97 upgradeBundlePackageBundlev1.Install();
98 upgradeBundlePackageBundlev1.VerifyRegisteredAndInPackageCache();
99 bundleAv1.VerifyRegisteredAndInPackageCache();
100
101 upgradeBundlePackageBundlev1.Uninstall();
102 upgradeBundlePackageBundlev1.VerifyUnregisteredAndRemovedFromPackageCache();
103 bundleAv1.VerifyRegisteredAndInPackageCache();
104 }
105
106 [Fact]
107 public void CanReferenceCountBundlePackage()
108 {
109 var bundleAv1 = this.CreateBundleInstaller(@"..\UpgradeRelatedBundleTests\BundleAv1");
110 var upgradeBundlePackageBundlev1 = this.CreateBundleInstaller("UpgradeBundlePackageBundlev1");
111
112 upgradeBundlePackageBundlev1.Install();
113 upgradeBundlePackageBundlev1.VerifyRegisteredAndInPackageCache();
114 bundleAv1.VerifyRegisteredAndInPackageCache(expectedSystemComponent: 1);
115
116 // Repair bundle so it adds itself as a reference to itself.
117 bundleAv1.Repair();
118 bundleAv1.VerifyRegisteredAndInPackageCache(expectedSystemComponent: 1);
119
120 upgradeBundlePackageBundlev1.Uninstall();
121 upgradeBundlePackageBundlev1.VerifyUnregisteredAndRemovedFromPackageCache();
122
123 bundleAv1.VerifyRegisteredAndInPackageCache(expectedSystemComponent: 1);
82 } 124 }
83 125
84 [Fact] 126 [Fact]
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/BurnCommon.cs b/src/wix/WixToolset.Core.Burn/Bundles/BurnCommon.cs
index 25c22361..4f1c7d84 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/BurnCommon.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/BurnCommon.cs
@@ -18,6 +18,7 @@ namespace WixToolset.Core.Burn.Bundles
18 /// </example> 18 /// </example>
19 internal abstract class BurnCommon : IDisposable 19 internal abstract class BurnCommon : IDisposable
20 { 20 {
21 public const string BurnV3Namespace = "http://schemas.microsoft.com/wix/2008/Burn";
21 public const string BurnNamespace = "http://wixtoolset.org/schemas/v4/2008/Burn"; 22 public const string BurnNamespace = "http://wixtoolset.org/schemas/v4/2008/Burn";
22 public const string BurnUXContainerEmbeddedIdFormat = "u{0}"; 23 public const string BurnUXContainerEmbeddedIdFormat = "u{0}";
23 public const string BurnAuthoredContainerEmbeddedIdFormat = "a{0}"; 24 public const string BurnAuthoredContainerEmbeddedIdFormat = "a{0}";
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
index 636c68cb..14d903db 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
@@ -390,6 +390,11 @@ namespace WixToolset.Core.Burn.Bundles
390 writer.WriteAttributeString("RepairArguments", bundlePackage.RepairCommand); 390 writer.WriteAttributeString("RepairArguments", bundlePackage.RepairCommand);
391 writer.WriteAttributeString("SupportsBurnProtocol", bundlePackage.SupportsBurnProtocol ? "yes" : "no"); 391 writer.WriteAttributeString("SupportsBurnProtocol", bundlePackage.SupportsBurnProtocol ? "yes" : "no");
392 writer.WriteAttributeString("Win64", bundlePackage.Win64 ? "yes" : "no"); 392 writer.WriteAttributeString("Win64", bundlePackage.Win64 ? "yes" : "no");
393
394 if (!package.PackageSymbol.Attributes.HasFlag(WixBundlePackageAttributes.Visible))
395 {
396 writer.WriteAttributeString("HideARP", "yes");
397 }
393 } 398 }
394 else if (package.SpecificPackageSymbol is WixBundleExePackageSymbol exePackage) // EXE 399 else if (package.SpecificPackageSymbol is WixBundleExePackageSymbol exePackage) // EXE
395 { 400 {
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs
index ff4a74a7..986b7605 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs
@@ -123,6 +123,13 @@ namespace WixToolset.Core.Burn.Bundles
123 return; 123 return;
124 } 124 }
125 125
126 if (BurnCommon.BurnV3Namespace == document.DocumentElement.NamespaceURI && !this.Facade.PackageSymbol.Attributes.HasFlag(WixBundlePackageAttributes.Visible))
127 {
128 this.Messaging.Write(BurnBackendWarnings.HiddenBundleNotSupported(packagePayload.SourceLineNumbers, sourcePath));
129
130 this.Facade.PackageSymbol.Attributes |= WixBundlePackageAttributes.Visible;
131 }
132
126 namespaceManager.AddNamespace("burn", document.DocumentElement.NamespaceURI); 133 namespaceManager.AddNamespace("burn", document.DocumentElement.NamespaceURI);
127 var registrationElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration", namespaceManager) as XmlElement; 134 var registrationElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration", namespaceManager) as XmlElement;
128 var arpElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration/burn:Arp", namespaceManager) as XmlElement; 135 var arpElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration/burn:Arp", namespaceManager) as XmlElement;
diff --git a/src/wix/WixToolset.Core.Burn/BurnBackendWarnings.cs b/src/wix/WixToolset.Core.Burn/BurnBackendWarnings.cs
index 6d45ff84..1f9a4102 100644
--- a/src/wix/WixToolset.Core.Burn/BurnBackendWarnings.cs
+++ b/src/wix/WixToolset.Core.Burn/BurnBackendWarnings.cs
@@ -36,6 +36,11 @@ namespace WixToolset.Core.Burn
36 return Message(sourceLineNumbers, Ids.UnknownBundleRelationAction, "The manifest for the bundle '{0}' contains an unknown related bundle action '{1}'. It will be ignored.", bundleExecutable, action); 36 return Message(sourceLineNumbers, Ids.UnknownBundleRelationAction, "The manifest for the bundle '{0}' contains an unknown related bundle action '{1}'. It will be ignored.", bundleExecutable, action);
37 } 37 }
38 38
39 public static Message HiddenBundleNotSupported(SourceLineNumber sourceLineNumbers, string bundleExecutable)
40 {
41 return Message(sourceLineNumbers, Ids.HiddenBundleNotSupported, "The bundle '{0}' does not support hiding its ARP registration.", bundleExecutable);
42 }
43
39 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) 44 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args)
40 { 45 {
41 return new Message(sourceLineNumber, MessageLevel.Warning, (int)id, format, args); 46 return new Message(sourceLineNumber, MessageLevel.Warning, (int)id, format, args);
@@ -49,6 +54,7 @@ namespace WixToolset.Core.Burn
49 FailedToExtractAttachedContainers = 8503, 54 FailedToExtractAttachedContainers = 8503,
50 UnknownCoffMachineType = 8504, 55 UnknownCoffMachineType = 8504,
51 UnknownBundleRelationAction = 8505, 56 UnknownBundleRelationAction = 8505,
57 HiddenBundleNotSupported = 8506,
52 } // last available is 8999. 9000 is VerboseMessages. 58 } // last available is 8999. 9000 is VerboseMessages.
53 } 59 }
54} 60}
diff --git a/src/wix/WixToolset.Core/Compiler_Bundle.cs b/src/wix/WixToolset.Core/Compiler_Bundle.cs
index 835fa2c2..2632a346 100644
--- a/src/wix/WixToolset.Core/Compiler_Bundle.cs
+++ b/src/wix/WixToolset.Core/Compiler_Bundle.cs
@@ -2106,7 +2106,7 @@ namespace WixToolset.Core
2106 break; 2106 break;
2107 case "Visible": 2107 case "Visible":
2108 visible = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); 2108 visible = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
2109 allowed = (packageType == WixBundlePackageType.Msi); 2109 allowed = (packageType == WixBundlePackageType.Bundle || packageType == WixBundlePackageType.Msi);
2110 break; 2110 break;
2111 case "Vital": 2111 case "Vital":
2112 vital = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); 2112 vital = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
@@ -2212,7 +2212,14 @@ namespace WixToolset.Core
2212 rollbackPathVariable = String.Concat("WixBundleRollbackLog_", id.Id); 2212 rollbackPathVariable = String.Concat("WixBundleRollbackLog_", id.Id);
2213 } 2213 }
2214 2214
2215 if (packageType == WixBundlePackageType.Exe) 2215 if (packageType == WixBundlePackageType.Bundle)
2216 {
2217 if (permanent == YesNoType.Yes && visible == YesNoType.NotSet)
2218 {
2219 visible = YesNoType.Yes;
2220 }
2221 }
2222 else if (packageType == WixBundlePackageType.Exe)
2216 { 2223 {
2217 // Set default scope for EXEs and MSPs if not already set. 2224 // Set default scope for EXEs and MSPs if not already set.
2218 if (perMachine == YesNoDefaultType.NotSet) 2225 if (perMachine == YesNoDefaultType.NotSet)
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs
index c2512d6f..7cd13ebf 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs
@@ -24,14 +24,19 @@ namespace WixToolsetTest.CoreIntegration
24 var baseFolder = fs.GetFolder(); 24 var baseFolder = fs.GetFolder();
25 var chainIntermediateFolder = Path.Combine(baseFolder, "obj", "Chain"); 25 var chainIntermediateFolder = Path.Combine(baseFolder, "obj", "Chain");
26 var parentIntermediateFolder = Path.Combine(baseFolder, "obj", "Parent"); 26 var parentIntermediateFolder = Path.Combine(baseFolder, "obj", "Parent");
27 var grandparentIntermediateFolder = Path.Combine(baseFolder, "obj", "Grandparent");
27 var binFolder = Path.Combine(baseFolder, "bin"); 28 var binFolder = Path.Combine(baseFolder, "bin");
28 var chainBundlePath = Path.Combine(binFolder, "chain.exe"); 29 var chainBundlePath = Path.Combine(binFolder, "chain.exe");
29 var chainPdbPath = Path.Combine(binFolder, "chain.wixpdb"); 30 var chainPdbPath = Path.Combine(binFolder, "chain.wixpdb");
30 var parentBundlePath = Path.Combine(binFolder, "parent.exe"); 31 var parentBundlePath = Path.Combine(binFolder, "parent.exe");
31 var parentPdbPath = Path.Combine(binFolder, "parent.wixpdb"); 32 var parentPdbPath = Path.Combine(binFolder, "parent.wixpdb");
32 var baFolderPath = Path.Combine(baseFolder, "ba"); 33 var grandparentBundlePath = Path.Combine(binFolder, "grandparent.exe");
34 var grandparentPdbPath = Path.Combine(binFolder, "grandparent.wixpdb");
35 var parentBaFolderPath = Path.Combine(baseFolder, "parentba");
36 var grandparentBaFolderPath = Path.Combine(baseFolder, "grandparentba");
33 var extractFolderPath = Path.Combine(baseFolder, "extract"); 37 var extractFolderPath = Path.Combine(baseFolder, "extract");
34 38
39 // chain.exe
35 var result = WixRunner.Execute(new[] 40 var result = WixRunner.Execute(new[]
36 { 41 {
37 "build", 42 "build",
@@ -57,6 +62,7 @@ namespace WixToolsetTest.CoreIntegration
57 chainBundleId = bundleSymbol.BundleId; 62 chainBundleId = bundleSymbol.BundleId;
58 } 63 }
59 64
65 // parent.exe
60 result = WixRunner.Execute(new[] 66 result = WixRunner.Execute(new[]
61 { 67 {
62 "build", 68 "build",
@@ -82,7 +88,7 @@ namespace WixToolsetTest.CoreIntegration
82 parentBundleId = bundleSymbol.BundleId; 88 parentBundleId = bundleSymbol.BundleId;
83 } 89 }
84 90
85 var extractResult = BundleExtractor.ExtractBAContainer(null, parentBundlePath, baFolderPath, extractFolderPath); 91 var extractResult = BundleExtractor.ExtractBAContainer(null, parentBundlePath, parentBaFolderPath, extractFolderPath);
86 extractResult.AssertSuccess(); 92 extractResult.AssertSuccess();
87 93
88 var ignoreAttributesByElementName = new Dictionary<string, List<string>> 94 var ignoreAttributesByElementName = new Dictionary<string, List<string>>
@@ -95,7 +101,7 @@ namespace WixToolsetTest.CoreIntegration
95 .ToArray(); 101 .ToArray();
96 WixAssert.CompareLineByLine(new string[] 102 WixAssert.CompareLineByLine(new string[]
97 { 103 {
98 $"<BundlePackage Id='chain.exe' Cache='keep' CacheId='{chainBundleId}v1.0.0.0' InstallSize='34' Size='*' PerMachine='yes' Permanent='no' Vital='yes' RollbackBoundaryForward='WixDefaultBoundary' RollbackBoundaryBackward='WixDefaultBoundary' LogPathVariable='WixBundleLog_chain.exe' RollbackLogPathVariable='WixBundleRollbackLog_chain.exe' BundleId='{chainBundleId}' Version='1.0.0.0' InstallArguments='' UninstallArguments='' RepairArguments='' SupportsBurnProtocol='yes' Win64='no'>" + 104 $"<BundlePackage Id='chain.exe' Cache='keep' CacheId='{chainBundleId}v1.0.0.0' InstallSize='34' Size='*' PerMachine='yes' Permanent='yes' Vital='yes' RollbackBoundaryForward='WixDefaultBoundary' RollbackBoundaryBackward='WixDefaultBoundary' LogPathVariable='WixBundleLog_chain.exe' RollbackLogPathVariable='WixBundleRollbackLog_chain.exe' BundleId='{chainBundleId}' Version='1.0.0.0' InstallArguments='' UninstallArguments='' RepairArguments='' SupportsBurnProtocol='yes' Win64='no' HideARP='yes'>" +
99 "<Provides Key='MyProviderKey,v1.0' Version='1.0.0.0' DisplayName='BurnBundle' Imported='yes' />" + 105 "<Provides Key='MyProviderKey,v1.0' Version='1.0.0.0' DisplayName='BurnBundle' Imported='yes' />" +
100 "<RelatedBundle Id='{B94478B1-E1F3-4700-9CE8-6AA090854AEC}' Action='Upgrade' />" + 106 "<RelatedBundle Id='{B94478B1-E1F3-4700-9CE8-6AA090854AEC}' Action='Upgrade' />" +
101 "<PayloadRef Id='chain.exe' />" + 107 "<PayloadRef Id='chain.exe' />" +
@@ -123,7 +129,77 @@ namespace WixToolsetTest.CoreIntegration
123 .ToArray(); 129 .ToArray();
124 WixAssert.CompareLineByLine(new string[] 130 WixAssert.CompareLineByLine(new string[]
125 { 131 {
126 "<WixPackageProperties Package='chain.exe' Vital='yes' DisplayName='BurnBundle' Description='BurnBundle' DownloadSize='*' PackageSize='*' InstalledSize='34' PackageType='Bundle' Permanent='no' LogPathVariable='WixBundleLog_chain.exe' RollbackLogPathVariable='WixBundleRollbackLog_chain.exe' Compressed='yes' Version='1.0.0.0' Cache='keep' />", 132 "<WixPackageProperties Package='chain.exe' Vital='yes' DisplayName='BurnBundle' Description='BurnBundle' DownloadSize='*' PackageSize='*' InstalledSize='34' PackageType='Bundle' Permanent='yes' LogPathVariable='WixBundleLog_chain.exe' RollbackLogPathVariable='WixBundleRollbackLog_chain.exe' Compressed='yes' Version='1.0.0.0' Cache='keep' />",
133 }, packageElements);
134
135 // grandparent.exe
136 result = WixRunner.Execute(new[]
137 {
138 "build",
139 Path.Combine(folder, "BundlePackage", "PermanentBundlePackage.wxs"),
140 "-bindpath", Path.Combine(folder, "SimpleBundle", "data"),
141 "-bindpath", binFolder,
142 "-intermediateFolder", grandparentIntermediateFolder,
143 "-o", grandparentBundlePath,
144 });
145
146 result.AssertSuccess();
147
148 Assert.True(File.Exists(grandparentBundlePath));
149
150 string grandparentBundleId;
151 using (var wixOutput = WixOutput.Read(grandparentPdbPath))
152 {
153
154 var intermediate = Intermediate.Load(wixOutput);
155 var section = intermediate.Sections.Single();
156
157 var bundleSymbol = section.Symbols.OfType<WixBundleSymbol>().Single();
158 grandparentBundleId = bundleSymbol.BundleId;
159 }
160
161 var grandparentExtractResult = BundleExtractor.ExtractBAContainer(null, grandparentBundlePath, grandparentBaFolderPath, extractFolderPath);
162 grandparentExtractResult.AssertSuccess();
163
164 ignoreAttributesByElementName = new Dictionary<string, List<string>>
165 {
166 { "BundlePackage", new List<string> { "Size" } },
167 };
168 bundlePackages = grandparentExtractResult.SelectManifestNodes("/burn:BurnManifest/burn:Chain/burn:BundlePackage")
169 .Cast<XmlElement>()
170 .Select(e => e.GetTestXml(ignoreAttributesByElementName))
171 .ToArray();
172 WixAssert.CompareLineByLine(new string[]
173 {
174 $"<BundlePackage Id='parent.exe' Cache='keep' CacheId='{parentBundleId}v1.0.1.0' InstallSize='34' Size='*' PerMachine='yes' Permanent='yes' Vital='yes' RollbackBoundaryForward='WixDefaultBoundary' RollbackBoundaryBackward='WixDefaultBoundary' LogPathVariable='WixBundleLog_parent.exe' RollbackLogPathVariable='WixBundleRollbackLog_parent.exe' BundleId='{parentBundleId}' Version='1.0.1.0' InstallArguments='' UninstallArguments='' RepairArguments='' SupportsBurnProtocol='yes' Win64='no'>" +
175 $"<Provides Key='{parentBundleId}' Version='1.0.1.0' DisplayName='BundlePackageBundle' Imported='yes' />" +
176 "<RelatedBundle Id='{4BE34BEE-CA23-488E-96A0-B15878E3654B}' Action='Upgrade' />" +
177 "<PayloadRef Id='parent.exe' />" +
178 "</BundlePackage>",
179 }, bundlePackages);
180
181 registrations = grandparentExtractResult.SelectManifestNodes("/burn:BurnManifest/burn:Registration")
182 .Cast<XmlElement>()
183 .Select(e => e.GetTestXml())
184 .ToArray();
185 WixAssert.CompareLineByLine(new string[]
186 {
187 $"<Registration Id='{grandparentBundleId}' ExecutableName='grandparent.exe' PerMachine='yes' Tag='' Version='1.0.2.0' ProviderKey='{grandparentBundleId}'>" +
188 "<Arp DisplayName='PermanentBundlePackageBundle' DisplayVersion='1.0.2.0' Publisher='Example Corporation' />" +
189 "</Registration>"
190 }, registrations);
191
192 ignoreAttributesByElementName = new Dictionary<string, List<string>>
193 {
194 { "WixPackageProperties", new List<string> { "DownloadSize", "PackageSize" } },
195 };
196 packageElements = grandparentExtractResult.SelectBADataNodes("/ba:BootstrapperApplicationData/ba:WixPackageProperties")
197 .Cast<XmlElement>()
198 .Select(e => e.GetTestXml(ignoreAttributesByElementName))
199 .ToArray();
200 WixAssert.CompareLineByLine(new string[]
201 {
202 "<WixPackageProperties Package='parent.exe' Vital='yes' DisplayName='BundlePackageBundle' Description='BundlePackageBundle' DownloadSize='*' PackageSize='*' InstalledSize='34' PackageType='Bundle' Permanent='yes' LogPathVariable='WixBundleLog_parent.exe' RollbackLogPathVariable='WixBundleRollbackLog_parent.exe' Compressed='yes' Version='1.0.1.0' Cache='keep' />",
127 }, packageElements); 203 }, packageElements);
128 } 204 }
129 } 205 }
@@ -136,6 +212,7 @@ namespace WixToolsetTest.CoreIntegration
136 using (var fs = new DisposableFileSystem()) 212 using (var fs = new DisposableFileSystem())
137 { 213 {
138 var baseFolder = fs.GetFolder(); 214 var baseFolder = fs.GetFolder();
215 var dotDataPath = Path.Combine(folder, ".Data");
139 var parentIntermediateFolder = Path.Combine(baseFolder, "obj", "Parent"); 216 var parentIntermediateFolder = Path.Combine(baseFolder, "obj", "Parent");
140 var binFolder = Path.Combine(baseFolder, "bin"); 217 var binFolder = Path.Combine(baseFolder, "bin");
141 var parentBundlePath = Path.Combine(binFolder, "parent.exe"); 218 var parentBundlePath = Path.Combine(binFolder, "parent.exe");
@@ -144,11 +221,11 @@ namespace WixToolsetTest.CoreIntegration
144 var extractFolderPath = Path.Combine(baseFolder, "extract"); 221 var extractFolderPath = Path.Combine(baseFolder, "extract");
145 string chainBundleId = "{215A70DB-AB35-48C7-BE51-D66EAAC87177}"; 222 string chainBundleId = "{215A70DB-AB35-48C7-BE51-D66EAAC87177}";
146 223
147 var result = WixRunner.Execute(new[] 224 var result = WixRunner.Execute(false, new[]
148 { 225 {
149 "build", 226 "build",
150 Path.Combine(folder, "BundlePackage", "V3BundlePackage.wxs"), 227 Path.Combine(folder, "BundlePackage", "V3BundlePackage.wxs"),
151 "-bindpath", Path.Combine(folder, ".Data"), 228 "-bindpath", dotDataPath,
152 "-bindpath", Path.Combine(folder, "SimpleBundle", "data"), 229 "-bindpath", Path.Combine(folder, "SimpleBundle", "data"),
153 "-intermediateFolder", parentIntermediateFolder, 230 "-intermediateFolder", parentIntermediateFolder,
154 "-o", parentBundlePath, 231 "-o", parentBundlePath,
@@ -156,6 +233,14 @@ namespace WixToolsetTest.CoreIntegration
156 233
157 result.AssertSuccess(); 234 result.AssertSuccess();
158 235
236 var warningMessages = result.Messages.Where(m => m.Level == MessageLevel.Warning)
237 .Select(m => m.ToString().Replace(dotDataPath, "<dotDataPath>"))
238 .ToArray();
239 WixAssert.CompareLineByLine(new[]
240 {
241 "The bundle '<dotDataPath>\\v3bundle.exe' does not support hiding its ARP registration.",
242 }, warningMessages);
243
159 Assert.True(File.Exists(parentBundlePath)); 244 Assert.True(File.Exists(parentBundlePath));
160 245
161 string parentBundleId; 246 string parentBundleId;
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/BundlePackage/BundlePackage.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/BundlePackage/BundlePackage.wxs
index 0602a48b..a1b182d3 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/BundlePackage/BundlePackage.wxs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/BundlePackage/BundlePackage.wxs
@@ -4,7 +4,7 @@
4 <BootstrapperApplicationDll SourceFile="fakeba.dll" /> 4 <BootstrapperApplicationDll SourceFile="fakeba.dll" />
5 </BootstrapperApplication> 5 </BootstrapperApplication>
6 <Chain> 6 <Chain>
7 <BundlePackage SourceFile="chain.exe" /> 7 <BundlePackage SourceFile="chain.exe" Visible="no" Permanent="yes" />
8 </Chain> 8 </Chain>
9 </Bundle> 9 </Bundle>
10</Wix> 10</Wix>
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/BundlePackage/PermanentBundlePackage.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/BundlePackage/PermanentBundlePackage.wxs
new file mode 100644
index 00000000..aee18e0f
--- /dev/null
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/BundlePackage/PermanentBundlePackage.wxs
@@ -0,0 +1,10 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 <Bundle Name="PermanentBundlePackageBundle" Version="1.0.2.0" Manufacturer="Example Corporation" UpgradeCode="{1752611C-3D8C-461E-A0A0-B0F07CBBD6FC}">
3 <BootstrapperApplication>
4 <BootstrapperApplicationDll SourceFile="fakeba.dll" />
5 </BootstrapperApplication>
6 <Chain>
7 <BundlePackage SourceFile="parent.exe" Permanent="yes" />
8 </Chain>
9 </Bundle>
10</Wix>