From 75f4dce4ea53b82f99932573f27ccfc799d0c5c1 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Mon, 4 Apr 2022 17:38:26 -0500 Subject: Add option for BundlePackage to be hidden in ARP like MsiPackage. Requires support for this feature in the nested bundle. Simplest implementation of 4454 --- src/burn/engine/bundlepackageengine.cpp | 10 +++ src/burn/engine/core.cpp | 29 +++++++ src/burn/engine/core.h | 2 + src/burn/engine/logging.cpp | 8 ++ src/burn/engine/package.h | 1 + src/burn/engine/plan.cpp | 5 ++ src/burn/engine/plan.h | 1 + src/burn/engine/registration.cpp | 2 +- src/burn/test/BurnUnitTest/PlanTest.cpp | 4 +- .../V3BundlePackageBundle.wixproj | 1 + src/test/burn/WixTestTools/BundleRegistration.cs | 3 + src/test/burn/WixTestTools/BundleVerifier.cs | 4 +- .../WixToolsetTest.BurnE2E/BundlePackageTests.cs | 50 ++++++++++- src/wix/WixToolset.Core.Burn/Bundles/BurnCommon.cs | 1 + .../Bundles/CreateBurnManifestCommand.cs | 5 ++ .../Bundles/ProcessBundlePackageCommand.cs | 7 ++ .../WixToolset.Core.Burn/BurnBackendWarnings.cs | 6 ++ src/wix/WixToolset.Core/Compiler_Bundle.cs | 11 ++- .../BundlePackageFixture.cs | 97 ++++++++++++++++++++-- .../TestData/BundlePackage/BundlePackage.wxs | 2 +- .../BundlePackage/PermanentBundlePackage.wxs | 10 +++ 21 files changed, 243 insertions(+), 16 deletions(-) create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/BundlePackage/PermanentBundlePackage.wxs (limited to 'src') 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( hr = XmlGetAttributeEx(pixnBundlePackage, L"RepairArguments", &pPackage->Bundle.sczRepairArguments); ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @RepairArguments."); + // @HideARP + hr = XmlGetYesNoAttribute(pixnBundlePackage, L"HideARP", &pPackage->Bundle.fHideARP); + ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @HideARP."); + // @SupportsBurnProtocol hr = XmlGetYesNoAttribute(pixnBundlePackage, L"SupportsBurnProtocol", &pPackage->Bundle.fSupportsBurnProtocol); ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @SupportsBurnProtocol."); @@ -870,6 +874,12 @@ static HRESULT ExecuteBundle( ExitOnFailure(hr, "Failed to append the parent to the command line."); } + if (pPackage->Bundle.fHideARP) + { + hr = StrAllocConcatFormatted(&sczBaseCommand, L" -%ls", BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT); + ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT); + } + // Add the list of dependencies to ignore, if any, to the burn command line. if (BOOTSTRAPPER_RELATION_CHAIN_PACKAGE == relationType) { 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( ExitOnFailure(hr, "Failed to append relation type to command-line."); } + if (pInternalCommand->fArpSystemComponent) + { + hr = StrAllocConcatFormatted(psczCommandLine, L" /%ls", BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT); + ExitOnFailure(hr, "Failed to append system component to command-line."); + } + if (fPassthrough) { hr = StrAllocConcatFormatted(psczCommandLine, L" /%ls", BURN_COMMANDLINE_SWITCH_PASSTHROUGH); @@ -1633,6 +1639,29 @@ extern "C" HRESULT CoreParseCommandLine( } } } + 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))) + { + // Get a pointer to the next character after the switch. + LPCWSTR wzParam = &argv[i][1 + lstrlenW(BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT)]; + + // Switch without an argument is allowed. An empty string means FALSE, everything else means TRUE. + if (L'\0' != wzParam[0]) + { + if (L'=' != wzParam[0]) + { + fInvalidCommandLine = TRUE; + TraceLog(E_INVALIDARG, "Invalid switch: %ls", argv[i]); + } + else + { + pInternalCommand->fArpSystemComponent = L'\0' != wzParam[1]; + } + } + else + { + pInternalCommand->fArpSystemComponent = TRUE; + } + } else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, BURN_COMMANDLINE_SWITCH_EMBEDDED, -1)) { 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"; const LPCWSTR BURN_COMMANDLINE_SWITCH_FILEHANDLE_ATTACHED = L"burn.filehandle.attached"; const LPCWSTR BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF = L"burn.filehandle.self"; const LPCWSTR BURN_COMMANDLINE_SWITCH_SPLASH_SCREEN = L"burn.splash.screen"; +const LPCWSTR BURN_COMMANDLINE_SWITCH_SYSTEM_COMPONENT = L"burn.system.component"; const LPCWSTR BURN_COMMANDLINE_SWITCH_PREFIX = L"burn."; const LPCWSTR BURN_BUNDLE_LAYOUT_DIRECTORY = L"WixBundleLayoutDirectory"; @@ -95,6 +96,7 @@ typedef struct _BURN_ENGINE_COMMAND BURN_MODE mode; BURN_AU_PAUSE_ACTION automaticUpdates; + BOOL fArpSystemComponent; BOOL fDisableSystemRestore; BOOL fInitiallyElevated; 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( return "CacheBundle"; case BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_PROVIDER_KEY: return "WriteProviderKey"; + case BURN_REGISTRATION_ACTION_OPERATIONS_ARP_SYSTEM_COMPONENT: + return "ArpSystemComponent"; case BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE + BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_PROVIDER_KEY: return "CacheBundle, WriteProviderKey"; + case BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE + BURN_REGISTRATION_ACTION_OPERATIONS_ARP_SYSTEM_COMPONENT: + return "CacheBundle, ArpSystemComponent"; + case BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_PROVIDER_KEY + BURN_REGISTRATION_ACTION_OPERATIONS_ARP_SYSTEM_COMPONENT: + return "WriteProviderKey, ArpSystemComponent"; + case BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE + BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_PROVIDER_KEY + BURN_REGISTRATION_ACTION_OPERATIONS_ARP_SYSTEM_COMPONENT: + return "CacheBundle, WriteProviderKey, ArpSystemComponent"; default: return "Invalid"; } 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 LPWSTR* rgsczPatchCodes; DWORD cPatchCodes; + BOOL fHideARP; BOOL fWin64; BOOL fSupportsBurnProtocol; 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( pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE; } + if (pPlan->pInternalCommand->fArpSystemComponent) + { + pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_ARP_SYSTEM_COMPONENT; + } + if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pPlan->action) { // 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 BURN_REGISTRATION_ACTION_OPERATIONS_NONE = 0x0, BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE = 0x1, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_PROVIDER_KEY = 0x2, + BURN_REGISTRATION_ACTION_OPERATIONS_ARP_SYSTEM_COMPONENT = 0x4, }; enum 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( } // Conditionally hide the ARP entry. - if (pRegistration->fForceSystemComponent) + if (pRegistration->fForceSystemComponent || (dwRegistrationOptions & BURN_REGISTRATION_ACTION_OPERATIONS_ARP_SYSTEM_COMPONENT)) { hr = RegWriteNumber(hkRegistration, REGISTRY_BUNDLE_SYSTEM_COMPONENT, 1); 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 BURN_ENGINE_STATE* pEngineState = &engineState; BURN_PLAN* pPlan = &engineState.plan; + pEngineState->internalCommand.fArpSystemComponent = TRUE; + InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState); DetectAttachedContainerAsAttached(pEngineState); DetectPackagesAsAbsent(pEngineState); @@ -1249,7 +1251,7 @@ namespace Bootstrapper Assert::Equal(FALSE, pPlan->fDisableRollback); Assert::Equal(FALSE, pPlan->fDisallowRemoval); Assert::Equal(FALSE, pPlan->fDowngrade); - Assert::Equal(BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE | BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_PROVIDER_KEY, pPlan->dwRegistrationOperations); + Assert::Equal(BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE | BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_PROVIDER_KEY | BURN_REGISTRATION_ACTION_OPERATIONS_ARP_SYSTEM_COMPONENT, pPlan->dwRegistrationOperations); BOOL fRollback = FALSE; 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 @@ TestBA_x64 {B6CAE45D-A7E5-4302-9FCF-4D05632F9FD7} x64 + 8506 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 public string Publisher { get; set; } + public int? SystemComponent { get; set; } + public string QuietUninstallString { get; set; } public string QuietUninstallCommand { get; set; } @@ -125,6 +127,7 @@ namespace WixTestTools registration.Installed = idKey.GetValue(REGISTRY_BUNDLE_INSTALLED) as int?; registration.ModifyPath = idKey.GetValue(REGISTRY_BUNDLE_MODIFY_PATH) as string; registration.Publisher = idKey.GetValue(REGISTRY_BUNDLE_PUBLISHER) as string; + registration.SystemComponent = idKey.GetValue(REGISTRY_BUNDLE_SYSTEM_COMPONENT) as int?; registration.UrlInfoAbout = idKey.GetValue(REGISTRY_BUNDLE_URL_INFO_ABOUT) as string; registration.UrlUpdateInfo = idKey.GetValue(REGISTRY_BUNDLE_URL_UPDATE_INFO) as string; 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 } } - public string VerifyRegisteredAndInPackageCache() + public string VerifyRegisteredAndInPackageCache(int? expectedSystemComponent = null) { Assert.True(this.TryGetRegistration(out var registration)); + Assert.Equal(expectedSystemComponent, registration.SystemComponent); + Assert.NotNull(registration.CachePath); Assert.True(File.Exists(registration.CachePath)); 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 multipleBundlePackagesBundle.Install(); multipleBundlePackagesBundle.VerifyRegisteredAndInPackageCache(); - bundleA.VerifyRegisteredAndInPackageCache(); - bundleB_x64.VerifyRegisteredAndInPackageCache(); + bundleA.VerifyRegisteredAndInPackageCache(expectedSystemComponent: 1); + bundleB_x64.VerifyRegisteredAndInPackageCache(expectedSystemComponent: 1); // Source file should be installed Assert.True(File.Exists(packageA32SourceCodeFilePath), $"Should have found PackageA payload installed at: {packageA32SourceCodeFilePath}"); @@ -61,14 +61,15 @@ namespace WixToolsetTest.BurnE2E upgradeBundlePackageBundlev2.Install(); upgradeBundlePackageBundlev2.VerifyRegisteredAndInPackageCache(); - bundleAv2.VerifyRegisteredAndInPackageCache(); + bundleAv2.VerifyRegisteredAndInPackageCache(expectedSystemComponent: 1); bundleAv1.VerifyUnregisteredAndRemovedFromPackageCache(); } [Fact] public void CanInstallV3BundlePackage() { - var v3BundleName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Package Cache", "{215a70db-ab35-48c7-be51-d66eaac87177}", "CustomV3Theme"); + var v3BundleId = "{215a70db-ab35-48c7-be51-d66eaac87177}"; + var v3BundleName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Package Cache", v3BundleId, "CustomV3Theme"); var v3Bundle = new BundleInstaller(this.TestContext, v3BundleName); this.AddBundleInstaller(v3Bundle); var v3BundlePackageBundle = this.CreateBundleInstaller("V3BundlePackageBundle"); @@ -79,6 +80,47 @@ namespace WixToolsetTest.BurnE2E v3BundlePackageBundle.VerifyRegisteredAndInPackageCache(); Assert.True(LogVerifier.MessageInLogFile(logPath, "Applied execute package: v3bundle.exe, result: 0x0, restart: None")); + + Assert.True(BundleRegistration.TryGetPerMachineBundleRegistrationById(v3BundleId, false, out var v3Registration)); + Assert.Null(v3Registration.SystemComponent); + } + + [Fact] + public void CanLeaveBundlePackageVisible() + { + var bundleAv1 = this.CreateBundleInstaller(@"..\UpgradeRelatedBundleTests\BundleAv1"); + var upgradeBundlePackageBundlev1 = this.CreateBundleInstaller("UpgradeBundlePackageBundlev1"); + + bundleAv1.Install(); + bundleAv1.VerifyRegisteredAndInPackageCache(); + + upgradeBundlePackageBundlev1.Install(); + upgradeBundlePackageBundlev1.VerifyRegisteredAndInPackageCache(); + bundleAv1.VerifyRegisteredAndInPackageCache(); + + upgradeBundlePackageBundlev1.Uninstall(); + upgradeBundlePackageBundlev1.VerifyUnregisteredAndRemovedFromPackageCache(); + bundleAv1.VerifyRegisteredAndInPackageCache(); + } + + [Fact] + public void CanReferenceCountBundlePackage() + { + var bundleAv1 = this.CreateBundleInstaller(@"..\UpgradeRelatedBundleTests\BundleAv1"); + var upgradeBundlePackageBundlev1 = this.CreateBundleInstaller("UpgradeBundlePackageBundlev1"); + + upgradeBundlePackageBundlev1.Install(); + upgradeBundlePackageBundlev1.VerifyRegisteredAndInPackageCache(); + bundleAv1.VerifyRegisteredAndInPackageCache(expectedSystemComponent: 1); + + // Repair bundle so it adds itself as a reference to itself. + bundleAv1.Repair(); + bundleAv1.VerifyRegisteredAndInPackageCache(expectedSystemComponent: 1); + + upgradeBundlePackageBundlev1.Uninstall(); + upgradeBundlePackageBundlev1.VerifyUnregisteredAndRemovedFromPackageCache(); + + bundleAv1.VerifyRegisteredAndInPackageCache(expectedSystemComponent: 1); } [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 /// internal abstract class BurnCommon : IDisposable { + public const string BurnV3Namespace = "http://schemas.microsoft.com/wix/2008/Burn"; public const string BurnNamespace = "http://wixtoolset.org/schemas/v4/2008/Burn"; public const string BurnUXContainerEmbeddedIdFormat = "u{0}"; 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 writer.WriteAttributeString("RepairArguments", bundlePackage.RepairCommand); writer.WriteAttributeString("SupportsBurnProtocol", bundlePackage.SupportsBurnProtocol ? "yes" : "no"); writer.WriteAttributeString("Win64", bundlePackage.Win64 ? "yes" : "no"); + + if (!package.PackageSymbol.Attributes.HasFlag(WixBundlePackageAttributes.Visible)) + { + writer.WriteAttributeString("HideARP", "yes"); + } } else if (package.SpecificPackageSymbol is WixBundleExePackageSymbol exePackage) // EXE { 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 return; } + if (BurnCommon.BurnV3Namespace == document.DocumentElement.NamespaceURI && !this.Facade.PackageSymbol.Attributes.HasFlag(WixBundlePackageAttributes.Visible)) + { + this.Messaging.Write(BurnBackendWarnings.HiddenBundleNotSupported(packagePayload.SourceLineNumbers, sourcePath)); + + this.Facade.PackageSymbol.Attributes |= WixBundlePackageAttributes.Visible; + } + namespaceManager.AddNamespace("burn", document.DocumentElement.NamespaceURI); var registrationElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration", namespaceManager) as XmlElement; 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 return Message(sourceLineNumbers, Ids.UnknownBundleRelationAction, "The manifest for the bundle '{0}' contains an unknown related bundle action '{1}'. It will be ignored.", bundleExecutable, action); } + public static Message HiddenBundleNotSupported(SourceLineNumber sourceLineNumbers, string bundleExecutable) + { + return Message(sourceLineNumbers, Ids.HiddenBundleNotSupported, "The bundle '{0}' does not support hiding its ARP registration.", bundleExecutable); + } + private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) { return new Message(sourceLineNumber, MessageLevel.Warning, (int)id, format, args); @@ -49,6 +54,7 @@ namespace WixToolset.Core.Burn FailedToExtractAttachedContainers = 8503, UnknownCoffMachineType = 8504, UnknownBundleRelationAction = 8505, + HiddenBundleNotSupported = 8506, } // last available is 8999. 9000 is VerboseMessages. } } 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 break; case "Visible": visible = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); - allowed = (packageType == WixBundlePackageType.Msi); + allowed = (packageType == WixBundlePackageType.Bundle || packageType == WixBundlePackageType.Msi); break; case "Vital": vital = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); @@ -2212,7 +2212,14 @@ namespace WixToolset.Core rollbackPathVariable = String.Concat("WixBundleRollbackLog_", id.Id); } - if (packageType == WixBundlePackageType.Exe) + if (packageType == WixBundlePackageType.Bundle) + { + if (permanent == YesNoType.Yes && visible == YesNoType.NotSet) + { + visible = YesNoType.Yes; + } + } + else if (packageType == WixBundlePackageType.Exe) { // Set default scope for EXEs and MSPs if not already set. 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 var baseFolder = fs.GetFolder(); var chainIntermediateFolder = Path.Combine(baseFolder, "obj", "Chain"); var parentIntermediateFolder = Path.Combine(baseFolder, "obj", "Parent"); + var grandparentIntermediateFolder = Path.Combine(baseFolder, "obj", "Grandparent"); var binFolder = Path.Combine(baseFolder, "bin"); var chainBundlePath = Path.Combine(binFolder, "chain.exe"); var chainPdbPath = Path.Combine(binFolder, "chain.wixpdb"); var parentBundlePath = Path.Combine(binFolder, "parent.exe"); var parentPdbPath = Path.Combine(binFolder, "parent.wixpdb"); - var baFolderPath = Path.Combine(baseFolder, "ba"); + var grandparentBundlePath = Path.Combine(binFolder, "grandparent.exe"); + var grandparentPdbPath = Path.Combine(binFolder, "grandparent.wixpdb"); + var parentBaFolderPath = Path.Combine(baseFolder, "parentba"); + var grandparentBaFolderPath = Path.Combine(baseFolder, "grandparentba"); var extractFolderPath = Path.Combine(baseFolder, "extract"); + // chain.exe var result = WixRunner.Execute(new[] { "build", @@ -57,6 +62,7 @@ namespace WixToolsetTest.CoreIntegration chainBundleId = bundleSymbol.BundleId; } + // parent.exe result = WixRunner.Execute(new[] { "build", @@ -82,7 +88,7 @@ namespace WixToolsetTest.CoreIntegration parentBundleId = bundleSymbol.BundleId; } - var extractResult = BundleExtractor.ExtractBAContainer(null, parentBundlePath, baFolderPath, extractFolderPath); + var extractResult = BundleExtractor.ExtractBAContainer(null, parentBundlePath, parentBaFolderPath, extractFolderPath); extractResult.AssertSuccess(); var ignoreAttributesByElementName = new Dictionary> @@ -95,7 +101,7 @@ namespace WixToolsetTest.CoreIntegration .ToArray(); WixAssert.CompareLineByLine(new string[] { - $"" + + $"" + "" + "" + "" + @@ -123,7 +129,77 @@ namespace WixToolsetTest.CoreIntegration .ToArray(); WixAssert.CompareLineByLine(new string[] { - "", + "", + }, packageElements); + + // grandparent.exe + result = WixRunner.Execute(new[] + { + "build", + Path.Combine(folder, "BundlePackage", "PermanentBundlePackage.wxs"), + "-bindpath", Path.Combine(folder, "SimpleBundle", "data"), + "-bindpath", binFolder, + "-intermediateFolder", grandparentIntermediateFolder, + "-o", grandparentBundlePath, + }); + + result.AssertSuccess(); + + Assert.True(File.Exists(grandparentBundlePath)); + + string grandparentBundleId; + using (var wixOutput = WixOutput.Read(grandparentPdbPath)) + { + + var intermediate = Intermediate.Load(wixOutput); + var section = intermediate.Sections.Single(); + + var bundleSymbol = section.Symbols.OfType().Single(); + grandparentBundleId = bundleSymbol.BundleId; + } + + var grandparentExtractResult = BundleExtractor.ExtractBAContainer(null, grandparentBundlePath, grandparentBaFolderPath, extractFolderPath); + grandparentExtractResult.AssertSuccess(); + + ignoreAttributesByElementName = new Dictionary> + { + { "BundlePackage", new List { "Size" } }, + }; + bundlePackages = grandparentExtractResult.SelectManifestNodes("/burn:BurnManifest/burn:Chain/burn:BundlePackage") + .Cast() + .Select(e => e.GetTestXml(ignoreAttributesByElementName)) + .ToArray(); + WixAssert.CompareLineByLine(new string[] + { + $"" + + $"" + + "" + + "" + + "", + }, bundlePackages); + + registrations = grandparentExtractResult.SelectManifestNodes("/burn:BurnManifest/burn:Registration") + .Cast() + .Select(e => e.GetTestXml()) + .ToArray(); + WixAssert.CompareLineByLine(new string[] + { + $"" + + "" + + "" + }, registrations); + + ignoreAttributesByElementName = new Dictionary> + { + { "WixPackageProperties", new List { "DownloadSize", "PackageSize" } }, + }; + packageElements = grandparentExtractResult.SelectBADataNodes("/ba:BootstrapperApplicationData/ba:WixPackageProperties") + .Cast() + .Select(e => e.GetTestXml(ignoreAttributesByElementName)) + .ToArray(); + WixAssert.CompareLineByLine(new string[] + { + "", }, packageElements); } } @@ -136,6 +212,7 @@ namespace WixToolsetTest.CoreIntegration using (var fs = new DisposableFileSystem()) { var baseFolder = fs.GetFolder(); + var dotDataPath = Path.Combine(folder, ".Data"); var parentIntermediateFolder = Path.Combine(baseFolder, "obj", "Parent"); var binFolder = Path.Combine(baseFolder, "bin"); var parentBundlePath = Path.Combine(binFolder, "parent.exe"); @@ -144,11 +221,11 @@ namespace WixToolsetTest.CoreIntegration var extractFolderPath = Path.Combine(baseFolder, "extract"); string chainBundleId = "{215A70DB-AB35-48C7-BE51-D66EAAC87177}"; - var result = WixRunner.Execute(new[] + var result = WixRunner.Execute(false, new[] { "build", Path.Combine(folder, "BundlePackage", "V3BundlePackage.wxs"), - "-bindpath", Path.Combine(folder, ".Data"), + "-bindpath", dotDataPath, "-bindpath", Path.Combine(folder, "SimpleBundle", "data"), "-intermediateFolder", parentIntermediateFolder, "-o", parentBundlePath, @@ -156,6 +233,14 @@ namespace WixToolsetTest.CoreIntegration result.AssertSuccess(); + var warningMessages = result.Messages.Where(m => m.Level == MessageLevel.Warning) + .Select(m => m.ToString().Replace(dotDataPath, "")) + .ToArray(); + WixAssert.CompareLineByLine(new[] + { + "The bundle '\\v3bundle.exe' does not support hiding its ARP registration.", + }, warningMessages); + Assert.True(File.Exists(parentBundlePath)); 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 @@ - + 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 @@ + + + + + + + + + + -- cgit v1.2.3-55-g6feb