@joebigelow / wix-1 / commits / fc3e4722

Add `ExePackage/@Bundle` to opt-in to v3 behavior. Automatically add '-norestart' for bundle ExePackages.

Add `ExePackage/@Bundle` to opt-in to v3 behavior. Automatically add '-norestart' for bundle ExePackages. Fixes 6252

Sean Hall committed Mar 21, 2022 at 23:22 UTC fc3e4722307c86b5d06918f0721b98323735bb40
16 files changed +233 -40
src/api/wix/WixToolset.Data/Symbols/WixBundleExePackageSymbol.cs
+3
@@ -39,6 +39,7 @@ namespace WixToolset.Data.Symbols
39 public enum WixBundleExePackageAttributes
40 {
41 None = 0,
42 + Bundle = 1,
43 }
44
45 public class WixBundleExePackageSymbol : IntermediateSymbol
@@ -89,6 +90,8 @@ namespace WixToolset.Data.Symbols
90 set => this.Set((int)WixBundleExePackageSymbolFields.ExeProtocol, value);
91 }
92
93 + public bool IsBundle => this.Attributes.HasFlag(WixBundleExePackageAttributes.Bundle);
94 +
95 public bool Repairable => this.RepairCommand != null;
96
97 public bool Uninstallable => this.UninstallCommand != null;
src/burn/engine/core.cpp
+5
@@ -234,6 +234,11 @@ extern "C" HRESULT CoreInitializeConstants(
234 pPackage->Bundle.wzAncestors = pRegistration->sczBundlePackageAncestors;
235 pPackage->Bundle.wzEngineWorkingDirectory = pInternalCommand->sczEngineWorkingDirectory;
236 }
237 + else if (BURN_PACKAGE_TYPE_EXE == pPackage->type && pPackage->Exe.fBundle)
238 + {
239 + pPackage->Exe.wzAncestors = pRegistration->sczBundlePackageAncestors;
240 + pPackage->Exe.wzEngineWorkingDirectory = pInternalCommand->sczEngineWorkingDirectory;
241 + }
242 }
243
244 LExit:
src/burn/engine/elevation.cpp
+44
@@ -940,6 +940,15 @@ extern "C" HRESULT ElevationExecuteExePackage(
940 hr = BuffWriteNumber(&pbData, &cbData, fRollback);
941 ExitOnFailure(hr, "Failed to write rollback.");
942
943 + hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczIgnoreDependencies);
944 + ExitOnFailure(hr, "Failed to write the list of dependencies to ignore to the message buffer.");
945 +
946 + hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczAncestors);
947 + ExitOnFailure(hr, "Failed to write the list of ancestors to the message buffer.");
948 +
949 + hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczEngineWorkingDirectory);
950 + ExitOnFailure(hr, "Failed to write the custom working directory to the message buffer.");
951 +
952 hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData);
953 ExitOnFailure(hr, "Failed to write variables.");
954
@@ -2844,6 +2853,9 @@ static HRESULT OnExecuteExePackage(
2853 LPWSTR sczPackage = NULL;
2854 DWORD dwRollback = 0;
2855 BURN_EXECUTE_ACTION executeAction = { };
2856 + LPWSTR sczIgnoreDependencies = NULL;
2857 + LPWSTR sczAncestors = NULL;
2858 + LPWSTR sczEngineWorkingDirectory = NULL;
2859 BOOTSTRAPPER_APPLY_RESTART exeRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
2860
2861 executeAction.type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE;
@@ -2858,6 +2870,15 @@ static HRESULT OnExecuteExePackage(
2870 hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback);
2871 ExitOnFailure(hr, "Failed to read rollback.");
2872
2873 + hr = BuffReadString(pbData, cbData, &iData, &sczIgnoreDependencies);
2874 + ExitOnFailure(hr, "Failed to read the list of dependencies to ignore.");
2875 +
2876 + hr = BuffReadString(pbData, cbData, &iData, &sczAncestors);
2877 + ExitOnFailure(hr, "Failed to read the list of ancestors.");
2878 +
2879 + hr = BuffReadString(pbData, cbData, &iData, &sczEngineWorkingDirectory);
2880 + ExitOnFailure(hr, "Failed to read the custom working directory.");
2881 +
2882 hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData);
2883 ExitOnFailure(hr, "Failed to read variables.");
2884
@@ -2869,11 +2890,34 @@ static HRESULT OnExecuteExePackage(
2890 ExitWithRootFailure(hr, E_INVALIDARG, "Package is not an EXE package: %ls", sczPackage);
2891 }
2892
2893 + // Pass the list of dependencies to ignore, if any, to the related bundle.
2894 + if (sczIgnoreDependencies && *sczIgnoreDependencies)
2895 + {
2896 + hr = StrAllocString(&executeAction.exePackage.sczIgnoreDependencies, sczIgnoreDependencies, 0);
2897 + ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
2898 + }
2899 +
2900 + // Pass the list of ancestors, if any, to the related bundle.
2901 + if (sczAncestors && *sczAncestors)
2902 + {
2903 + hr = StrAllocString(&executeAction.exePackage.sczAncestors, sczAncestors, 0);
2904 + ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
2905 + }
2906 +
2907 + if (sczEngineWorkingDirectory && *sczEngineWorkingDirectory)
2908 + {
2909 + hr = StrAllocString(&executeAction.exePackage.sczEngineWorkingDirectory, sczEngineWorkingDirectory, 0);
2910 + ExitOnFailure(hr, "Failed to allocate the custom working directory.");
2911 + }
2912 +
2913 // Execute EXE package.
2914 hr = ExeEngineExecutePackage(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &exeRestart);
2915 ExitOnFailure(hr, "Failed to execute EXE package.");
2916
2917 LExit:
2918 + ReleaseStr(sczEngineWorkingDirectory);
2919 + ReleaseStr(sczAncestors);
2920 + ReleaseStr(sczIgnoreDependencies);
2921 ReleaseStr(sczPackage);
2922 PlanUninitializeExecuteAction(&executeAction);
2923
src/burn/engine/exeengine.cpp
+79 -12
@@ -40,6 +40,10 @@ extern "C" HRESULT ExeEngineParsePackageFromXml(
40 hr = XmlGetYesNoAttribute(pixnExePackage, L"Uninstallable", &pPackage->Exe.fUninstallable);
41 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @Uninstallable.");
42
43 + // @Bundle
44 + hr = XmlGetYesNoAttribute(pixnExePackage, L"Bundle", &pPackage->Exe.fBundle);
45 + ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @Bundle.");
46 +
47 // @Protocol
48 hr = XmlGetAttributeEx(pixnExePackage, L"Protocol", &scz);
49 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @Protocol.");
@@ -87,6 +91,7 @@ extern "C" void ExeEnginePackageUninitialize(
91 ReleaseStr(pPackage->Exe.sczInstallArguments);
92 ReleaseStr(pPackage->Exe.sczRepairArguments);
93 ReleaseStr(pPackage->Exe.sczUninstallArguments);
94 + ReleaseStr(pPackage->Exe.sczIgnoreDependencies);
95 ReleaseMem(pPackage->Exe.rgExitCodes);
96
97 // free command-line arguments
@@ -286,6 +291,24 @@ extern "C" HRESULT ExeEnginePlanAddPackage(
291 pAction->exePackage.pPackage = pPackage;
292 pAction->exePackage.action = pPackage->rollback;
293
294 + if (pPackage->Exe.sczIgnoreDependencies)
295 + {
296 + hr = StrAllocString(&pAction->exePackage.sczIgnoreDependencies, pPackage->Exe.sczIgnoreDependencies, 0);
297 + ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
298 + }
299 +
300 + if (pPackage->Exe.wzAncestors)
301 + {
302 + hr = StrAllocString(&pAction->exePackage.sczAncestors, pPackage->Exe.wzAncestors, 0);
303 + ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
304 + }
305 +
306 + if (pPackage->Exe.wzEngineWorkingDirectory)
307 + {
308 + hr = StrAllocString(&pAction->exePackage.sczEngineWorkingDirectory, pPackage->Exe.wzEngineWorkingDirectory, 0);
309 + ExitOnFailure(hr, "Failed to allocate the custom working directory.");
310 + }
311 +
312 LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, NULL); // ignore errors.
313
314 hr = PlanExecuteCheckpoint(pPlan);
@@ -302,6 +325,24 @@ extern "C" HRESULT ExeEnginePlanAddPackage(
325 pAction->exePackage.pPackage = pPackage;
326 pAction->exePackage.action = pPackage->execute;
327
328 + if (pPackage->Exe.sczIgnoreDependencies)
329 + {
330 + hr = StrAllocString(&pAction->exePackage.sczIgnoreDependencies, pPackage->Exe.sczIgnoreDependencies, 0);
331 + ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
332 + }
333 +
334 + if (pPackage->Exe.wzAncestors)
335 + {
336 + hr = StrAllocString(&pAction->exePackage.sczAncestors, pPackage->Exe.wzAncestors, 0);
337 + ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
338 + }
339 +
340 + if (pPackage->Exe.wzEngineWorkingDirectory)
341 + {
342 + hr = StrAllocString(&pAction->exePackage.sczEngineWorkingDirectory, pPackage->Exe.wzEngineWorkingDirectory, 0);
343 + ExitOnFailure(hr, "Failed to allocate the custom working directory.");
344 + }
345 +
346 LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, NULL); // ignore errors.
347 }
348
@@ -406,27 +447,53 @@ extern "C" HRESULT ExeEngineExecutePackage(
447 }
448
449 // build command
409 - if (*sczArguments)
450 + AppAppendCommandLineArgument(&sczCommand, sczExecutablePath);
451 + ExitOnFailure(hr, "Failed to create executable command.");
452 +
453 + if (pPackage->Exe.fBundle)
454 + {
455 + hr = StrAllocConcat(&sczCommand, L" -norestart", 0);
456 + ExitOnFailure(hr, "Failed to append quiet argument.");
457 +
458 + // Add the list of dependencies to ignore, if any, to the burn command line.
459 + if (pExecuteAction->exePackage.sczIgnoreDependencies)
460 + {
461 + hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies);
462 + ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line.");
463 + }
464 +
465 + // Add the list of ancestors, if any, to the burn command line.
466 + if (pExecuteAction->exePackage.sczAncestors)
467 + {
468 + hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", sczCommand, BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->exePackage.sczAncestors);
469 + ExitOnFailure(hr, "Failed to append the list of ancestors to the command line.");
470 + }
471 +
472 + if (pExecuteAction->exePackage.sczEngineWorkingDirectory)
473 + {
474 + hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->exePackage.sczEngineWorkingDirectory, &sczCommand, NULL);
475 + ExitOnFailure(hr, "Failed to append the custom working directory to the exepackage command line.");
476 + }
477 +
478 + hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczCommand, NULL);
479 + ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF);
480 + }
481 +
482 + // Always add user supplied arguments last.
483 + if (sczArguments && *sczArguments)
484 {
485 hr = VariableFormatString(pVariables, sczArguments, &sczArgumentsFormatted, NULL);
486 ExitOnFailure(hr, "Failed to format argument string.");
487
414 - hr = StrAllocFormattedSecure(&sczCommand, L"\"%ls\" %ls", sczExecutablePath, sczArgumentsFormatted);
415 - ExitOnFailure(hr, "Failed to create executable command.");
416 -
488 hr = VariableFormatStringObfuscated(pVariables, sczArguments, &sczArgumentsObfuscated, NULL);
489 ExitOnFailure(hr, "Failed to format obfuscated argument string.");
490
420 - hr = StrAllocFormatted(&sczCommandObfuscated, L"\"%ls\" %ls", sczExecutablePath, sczArgumentsObfuscated);
421 - }
422 - else
423 - {
424 - hr = StrAllocFormatted(&sczCommand, L"\"%ls\"", sczExecutablePath);
425 - ExitOnFailure(hr, "Failed to create executable command.");
491 + hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczCommand, sczArgumentsObfuscated);
492 + ExitOnFailure(hr, "Failed to copy obfuscated formatted arguments.");
493
427 - hr = StrAllocFormatted(&sczCommandObfuscated, L"\"%ls\"", sczExecutablePath);
494 + hr = StrAllocConcatFormattedSecure(&sczCommand, L" %ls", sczArgumentsFormatted);
495 + ExitOnFailure(hr, "Failed to copy formatted arguments.");
496 }
429 - ExitOnFailure(hr, "Failed to create obfuscated executable command.");
497
498 // Log before we add the secret pipe name and client token for embedded processes.
499 LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated);
src/burn/engine/package.h
+4
@@ -324,7 +324,11 @@ typedef struct _BURN_PACKAGE
324 LPWSTR sczInstallArguments;
325 LPWSTR sczRepairArguments;
326 LPWSTR sczUninstallArguments;
327 + LPWSTR sczIgnoreDependencies;
328 + LPCWSTR wzAncestors; // points directly into engine state.
329 + LPCWSTR wzEngineWorkingDirectory; // points directly into engine state.
330
331 + BOOL fBundle;
332 BOOL fPseudoPackage;
333 BOOL fFireAndForget;
334 BOOL fRepairable;
src/burn/engine/plan.cpp
+22 -11
@@ -291,6 +291,12 @@ extern "C" void PlanUninitializeExecuteAction(
291 ReleaseStr(pExecuteAction->relatedBundle.sczEngineWorkingDirectory);
292 break;
293
294 + case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
295 + ReleaseStr(pExecuteAction->exePackage.sczIgnoreDependencies);
296 + ReleaseStr(pExecuteAction->exePackage.sczAncestors);
297 + ReleaseStr(pExecuteAction->exePackage.sczEngineWorkingDirectory);
298 + break;
299 +
300 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
301 ReleaseStr(pExecuteAction->msiPackage.sczLogPath);
302 ReleaseMem(pExecuteAction->msiPackage.rgFeatures);
@@ -1495,26 +1501,21 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1501 for (DWORD i = 0; i < pPlan->cExecuteActions; ++i)
1502 {
1503 BOOTSTRAPPER_ACTION_STATE packageAction = BOOTSTRAPPER_ACTION_STATE_NONE;
1504 + BURN_PACKAGE* pPackage = &pPlan->rgExecuteActions[i].relatedBundle.pRelatedBundle->package;
1505 + BOOL fBundle = FALSE;
1506
1507 switch (pPlan->rgExecuteActions[i].type)
1508 {
1509 case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
1510 packageAction = pPlan->rgExecuteActions[i].relatedBundle.action;
1503 -
1504 - if (BOOTSTRAPPER_ACTION_STATE_NONE != packageAction)
1505 - {
1506 - BURN_PACKAGE* pPackage = &pPlan->rgExecuteActions[i].relatedBundle.pRelatedBundle->package;
1507 - if (pPackage->cDependencyProviders)
1508 - {
1509 - // Bundles only support a single provider key.
1510 - const BURN_DEPENDENCY_PROVIDER* pProvider = pPackage->rgDependencyProviders;
1511 - DictAddKey(sdProviderKeys, pProvider->sczKey);
1512 - }
1513 - }
1511 + pPackage = &pPlan->rgExecuteActions[i].relatedBundle.pRelatedBundle->package;
1512 + fBundle = TRUE;
1513 break;
1514
1515 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
1516 packageAction = pPlan->rgExecuteActions[i].exePackage.action;
1517 + pPackage = pPlan->rgExecuteActions[i].exePackage.pPackage;
1518 + fBundle = TRUE;
1519 break;
1520
1521 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
@@ -1530,6 +1531,16 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1531 break;
1532 }
1533
1534 + if (fBundle && BOOTSTRAPPER_ACTION_STATE_NONE != packageAction)
1535 + {
1536 + if (pPackage->cDependencyProviders)
1537 + {
1538 + // Bundles only support a single provider key.
1539 + const BURN_DEPENDENCY_PROVIDER* pProvider = pPackage->rgDependencyProviders;
1540 + DictAddKey(sdProviderKeys, pProvider->sczKey);
1541 + }
1542 + }
1543 +
1544 fExecutingAnyPackage |= BOOTSTRAPPER_ACTION_STATE_NONE != packageAction;
1545 fInstallingAnyPackage |= BOOTSTRAPPER_ACTION_STATE_INSTALL == packageAction || BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE == packageAction;
1546 }
src/burn/engine/plan.h
+3
@@ -164,6 +164,9 @@ typedef struct _BURN_EXECUTE_ACTION
164 {
165 BURN_PACKAGE* pPackage;
166 BOOTSTRAPPER_ACTION_STATE action;
167 + LPWSTR sczIgnoreDependencies;
168 + LPWSTR sczAncestors;
169 + LPWSTR sczEngineWorkingDirectory;
170 } exePackage;
171 struct
172 {
src/burn/test/BurnUnitTest/PlanTest.cpp
+6 -4
@@ -716,7 +716,7 @@ namespace Bootstrapper
716 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
717 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"ExeA");
718 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
719 - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"ExeA", BOOTSTRAPPER_ACTION_STATE_INSTALL);
719 + ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"ExeA", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
720 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
721 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
722 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
@@ -727,7 +727,7 @@ namespace Bootstrapper
727 dwExecuteCheckpointId = 2;
728 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
729 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
730 - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"ExeA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL);
730 + ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"ExeA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
731 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
732 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
733 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -2125,7 +2125,7 @@ namespace Bootstrapper
2125 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
2126 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2127 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web");
2128 - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web", BOOTSTRAPPER_ACTION_STATE_INSTALL);
2128 + ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
2129 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2130 dwExecuteCheckpointId += 1; // cache checkpoints
2131 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -2683,13 +2683,15 @@ namespace Bootstrapper
2683 __in BOOL fRollback,
2684 __in DWORD dwIndex,
2685 __in LPCWSTR wzPackageId,
2686 - __in BOOTSTRAPPER_ACTION_STATE action
2686 + __in BOOTSTRAPPER_ACTION_STATE action,
2687 + __in LPCWSTR wzIgnoreDependencies
2688 )
2689 {
2690 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
2691 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE, pAction->type);
2692 NativeAssert::StringEqual(wzPackageId, pAction->exePackage.pPackage->sczId);
2693 Assert::Equal<DWORD>(action, pAction->exePackage.action);
2694 + NativeAssert::StringEqual(wzIgnoreDependencies, pAction->exePackage.sczIgnoreDependencies);
2695 Assert::Equal<BOOL>(FALSE, pAction->fDeleted);
2696 }
2697
src/ext/NetFx/wixlib/NetCore3.1.12_x64.wxs
+2 -2
@@ -20,7 +20,7 @@
20 <WixVariable Id="AspNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)RepairArguments" Value="" Overridable="yes" />
21
22 <PackageGroup Id="$(var.AspNetCoreRedistId)">
23 - <ExePackage InstallArguments="$(var.AspNetCoreRedistInstallArguments)" PerMachine="yes" DetectCondition="!(wix.AspNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)DetectCondition)" InstallCondition="!(wix.AspNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)InstallCondition)" Id="$(var.AspNetCoreRedistId)" Vital="yes" Permanent="yes" Protocol="burn" LogPathVariable="$(var.AspNetCoreRedistLog)" Cache="remove">
23 + <ExePackage InstallArguments="$(var.AspNetCoreRedistInstallArguments)" PerMachine="yes" DetectCondition="!(wix.AspNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)DetectCondition)" InstallCondition="!(wix.AspNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)InstallCondition)" Id="$(var.AspNetCoreRedistId)" Vital="yes" Permanent="yes" Bundle="yes" LogPathVariable="$(var.AspNetCoreRedistLog)" Cache="remove">
24 <ExePackagePayload Name="!(wix.AspNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)PackageDirectory)aspnetcore-runtime-$(var.NetCoreVersion)-win-$(var.NetCorePlatform).exe" DownloadUrl="$(var.AspNetCoreRedistLink)" ProductName="Microsoft ASP.NET Core 3.1.12 - Shared Framework" Description="Microsoft ASP.NET Core 3.1.12 - Shared Framework" CertificatePublicKey="3756E9BBF4461DCD0AA68E0D1FCFFA9CEA47AC18" CertificateThumbprint="2485A7AFA98E178CB8F30C9838346B514AEA4769" Hash="5CE9839CAE90FB2936033431F2905E97C7DC080DC50108D58714939CCCC6A265694B8259A3BF742A68BF04D9CFFB0602B0306DD401C4CE644BDB96C7D1168E59" Size="7841808" Version="3.1.12.21070" />
25 </ExePackage>
26 </PackageGroup>
@@ -35,7 +35,7 @@
35 <WixVariable Id="DesktopNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)RepairArguments" Value="" Overridable="yes" />
36
37 <PackageGroup Id="$(var.DesktopNetCoreRedistId)">
38 - <ExePackage InstallArguments="$(var.DesktopNetCoreRedistInstallArguments)" PerMachine="yes" DetectCondition="!(wix.DesktopNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)DetectCondition)" InstallCondition="!(wix.DesktopNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)InstallCondition)" Id="$(var.DesktopNetCoreRedistId)" Vital="yes" Permanent="yes" Protocol="burn" LogPathVariable="$(var.DesktopNetCoreRedistLog)" Cache="remove">
38 + <ExePackage InstallArguments="$(var.DesktopNetCoreRedistInstallArguments)" PerMachine="yes" DetectCondition="!(wix.DesktopNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)DetectCondition)" InstallCondition="!(wix.DesktopNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)InstallCondition)" Id="$(var.DesktopNetCoreRedistId)" Vital="yes" Permanent="yes" Bundle="yes" LogPathVariable="$(var.DesktopNetCoreRedistLog)" Cache="remove">
39 <ExePackagePayload Name="!(wix.DesktopNetCoreRuntime$(var.NetCoreIdVersion)Redist$(var.NetCorePlatform)PackageDirectory)windowsdesktop-runtime-$(var.NetCoreVersion)-win-$(var.NetCorePlatform).exe" DownloadUrl="$(var.DesktopNetCoreRedistLink)" ProductName="Microsoft Windows Desktop Runtime - 3.1.12 (x64)" Description="Microsoft Windows Desktop Runtime - 3.1.12 (x64)" CertificatePublicKey="3756E9BBF4461DCD0AA68E0D1FCFFA9CEA47AC18" CertificateThumbprint="2485A7AFA98E178CB8F30C9838346B514AEA4769" Hash="CD69B8722B2FF175FADD6774AB6A97F89292FC57A15CEC95218E79FFF1E26F46A7EFFFB15CE0F6D22B83B991F7083BB5C04F5158F87D298EA0F204933F8ECD27" Size="54284816" Version="3.1.12.29719" />
40 </ExePackage>
41 </PackageGroup>
src/ext/NetFx/wixlib/NetCore3_Platform.wxi
+6 -6
@@ -6,20 +6,20 @@
6 <?define AspNetCoreId = ASPNETCORERUNTIME$(var.NetCoreIdVersion)_$(var.NetCorePlatform)?>
7 <?define AspNetCoreRedistId = AspNetCoreRuntime$(var.NetCoreIdVersion)Redist_$(var.NetCorePlatform)?>
8 <?define AspNetCoreRedistLog = AspNetCoreRuntime$(var.NetCoreIdVersion)RedistLog?>
9 - <?define AspNetCoreRedistInstallArguments = /install /quiet /norestart /log &quot;[$(var.AspNetCoreRedistLog)]&quot;?>
10 - <?define AspNetCoreRedistUninstallArguments = /uninstall /quiet /norestart /log &quot;[$(var.AspNetCoreRedistLog)]&quot;?>
9 + <?define AspNetCoreRedistInstallArguments = /install /quiet /log &quot;[$(var.AspNetCoreRedistLog)]&quot;?>
10 + <?define AspNetCoreRedistUninstallArguments = /uninstall /quiet /log &quot;[$(var.AspNetCoreRedistLog)]&quot;?>
11
12 <?define DesktopNetCoreId = DESKTOPNETCORERUNTIME$(var.NetCoreIdVersion)_$(var.NetCorePlatform)?>
13 <?define DesktopNetCoreRedistId = DesktopNetCoreRuntime$(var.NetCoreIdVersion)Redist_$(var.NetCorePlatform)?>
14 <?define DesktopNetCoreRedistLog = DesktopNetCoreRuntime$(var.NetCoreIdVersion)RedistLog?>
15 - <?define DesktopNetCoreRedistInstallArguments = /install /quiet /norestart /log &quot;[$(var.DesktopNetCoreRedistLog)]&quot;?>
16 - <?define DesktopNetCoreRedistUninstallArguments = /uninstall /quiet /norestart /log &quot;[$(var.DesktopNetCoreRedistLog)]&quot;?>
15 + <?define DesktopNetCoreRedistInstallArguments = /install /quiet /log &quot;[$(var.DesktopNetCoreRedistLog)]&quot;?>
16 + <?define DesktopNetCoreRedistUninstallArguments = /uninstall /quiet /log &quot;[$(var.DesktopNetCoreRedistLog)]&quot;?>
17
18 <?define DotNetCoreId = DOTNETCORERUNTIME$(var.NetCoreIdVersion)_$(var.NetCorePlatform)?>
19 <?define DotNetCoreRedistId = DotNetCoreRuntime$(var.NetCoreIdVersion)Redist_$(var.NetCorePlatform)?>
20 <?define DotNetCoreRedistLog = DotNetCoreRuntime$(var.NetCoreIdVersion)RedistLog?>
21 - <?define DotNetCoreRedistInstallArguments = /install /quiet /norestart /log &quot;[$(var.DotNetCoreRedistLog)]&quot;?>
22 - <?define DotNetCoreRedistUninstallArguments = /uninstall /quiet /norestart /log &quot;[$(var.DotNetCoreRedistLog)]&quot;?>
21 + <?define DotNetCoreRedistInstallArguments = /install /quiet /log &quot;[$(var.DotNetCoreRedistLog)]&quot;?>
22 + <?define DotNetCoreRedistUninstallArguments = /uninstall /quiet /log &quot;[$(var.DotNetCoreRedistLog)]&quot;?>
23
24 <?define DotNetHomeId = DOTNETHOME_$(var.NetCorePlatform)?>
25 <?define NetCoreEulaLink = https://go.microsoft.com/fwlink/?LinkId=329770?>
src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
+6
@@ -389,10 +389,16 @@ namespace WixToolset.Core.Burn.Bundles
389 writer.WriteAttributeString("Uninstallable", exePackage.Uninstallable ? "yes" : "no");
390 writer.WriteAttributeString("RepairArguments", exePackage.RepairCommand);
391 writer.WriteAttributeString("Repairable", exePackage.Repairable ? "yes" : "no");
392 +
393 if (!String.IsNullOrEmpty(exePackage.ExeProtocol))
394 {
395 writer.WriteAttributeString("Protocol", exePackage.ExeProtocol);
396 }
397 +
398 + if (exePackage.IsBundle)
399 + {
400 + writer.WriteAttributeString("Bundle", "yes");
401 + }
402 }
403 else if (package.SpecificPackageSymbol is WixBundleMsiPackageSymbol msiPackage) // MSI
404 {
src/wix/WixToolset.Core/Compiler_Bundle.cs
+18 -1
@@ -1999,6 +1999,7 @@ namespace WixToolset.Core
1999 var enableFeatureSelection = YesNoType.NotSet;
2000 var forcePerMachine = YesNoType.NotSet;
2001 CompilerPayload childPackageCompilerPayload = null;
2002 + var bundle = YesNoType.NotSet;
2003 var slipstream = YesNoType.NotSet;
2004 var hasPayloadInfo = false;
2005
@@ -2089,6 +2090,10 @@ namespace WixToolset.Core
2090 case "Vital":
2091 vital = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
2092 break;
2093 + case "Bundle":
2094 + bundle = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
2095 + allowed = (packageType == WixBundlePackageType.Exe);
2096 + break;
2097 case "InstallArguments":
2098 installArguments = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2099 allowed = (packageType == WixBundlePackageType.Exe);
@@ -2248,12 +2253,21 @@ namespace WixToolset.Core
2253 this.Core.Write(WarningMessages.AttributeShouldContain(sourceLineNumbers, node.Name.LocalName, "UninstallArguments", uninstallArguments, expectedArgument, "Protocol", "netfx4"));
2254 }
2255 }
2256 +
2257 + if (bundle == YesNoType.Yes)
2258 + {
2259 + this.Core.Write(ErrorMessages.IllegalAttributeValueWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "Protocol", protocol, "Bundle", "yes"));
2260 + }
2261 }
2262 else if (!protocol.Equals("burn", StringComparison.Ordinal) && !protocol.Equals("none", StringComparison.Ordinal))
2263 {
2264 this.Core.Write(ErrorMessages.IllegalAttributeValueWithLegalList(sourceLineNumbers, node.Name.LocalName, "Protocol", protocol, "none, burn, netfx4"));
2265 }
2266 }
2267 + else if (bundle == YesNoType.Yes)
2268 + {
2269 + protocol = "burn";
2270 + }
2271 }
2272 else if (packageType == WixBundlePackageType.Msp)
2273 {
@@ -2409,9 +2423,12 @@ namespace WixToolset.Core
2423 switch (packageType)
2424 {
2425 case WixBundlePackageType.Exe:
2426 + WixBundleExePackageAttributes exeAttributes = 0;
2427 + exeAttributes |= (YesNoType.Yes == bundle) ? WixBundleExePackageAttributes.Bundle : 0;
2428 +
2429 this.Core.AddSymbol(new WixBundleExePackageSymbol(sourceLineNumbers, id)
2430 {
2414 - Attributes = WixBundleExePackageAttributes.None,
2431 + Attributes = exeAttributes,
2432 DetectCondition = detectCondition,
2433 InstallCommand = installArguments,
2434 RepairCommand = repairArguments,
src/wix/test/WixToolsetTest.CoreIntegration/BadInputFixture.cs
+23
@@ -85,6 +85,29 @@ namespace WixToolsetTest.CoreIntegration
85 }
86 }
87
88 + [Fact]
89 + public void BundleExePackageWithNetfxProtocolIsRejected()
90 + {
91 + var folder = TestData.Get(@"TestData\BadInput");
92 +
93 + using (var fs = new DisposableFileSystem())
94 + {
95 + var baseFolder = fs.GetFolder();
96 + var intermediateFolder = Path.Combine(baseFolder, "obj");
97 + var wixlibPath = Path.Combine(intermediateFolder, @"test.wixlib");
98 +
99 + var result = WixRunner.Execute(new[]
100 + {
101 + "build",
102 + Path.Combine(folder, "BundleExePackageWithNetfxProtocol.wxs"),
103 + "-intermediateFolder", intermediateFolder,
104 + "-o", wixlibPath,
105 + });
106 +
107 + Assert.Equal(193, result.ExitCode);
108 + }
109 + }
110 +
111 [Fact]
112 public void BundleVariableWithBadTypeIsRejected()
113 {
src/wix/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs
+2 -2
@@ -354,8 +354,8 @@ namespace WixToolsetTest.CoreIntegration
354 { "ExePackage", new List<string> { "CacheId", "InstallSize", "Size" } },
355 };
356 Assert.Equal(2, exePackageElements.Count);
357 - Assert.Equal("<ExePackage Id='credwiz.exe' Cache='keep' CacheId='*' InstallSize='*' Size='*' PerMachine='yes' Permanent='yes' Vital='yes' RollbackBoundaryForward='WixDefaultBoundary' LogPathVariable='WixBundleLog_credwiz.exe' RollbackLogPathVariable='WixBundleRollbackLog_credwiz.exe' DetectCondition='none' InstallArguments='' UninstallArguments='-foo' Uninstallable='yes' RepairArguments='' Repairable='no'><PayloadRef Id='credwiz.exe' /><PayloadRef Id='SourceFilePayload' /></ExePackage>", exePackageElements[0].GetTestXml(ignoreAttributesByElementName));
358 - Assert.Equal("<ExePackage Id='cscript.exe' Cache='keep' CacheId='*' InstallSize='*' Size='*' PerMachine='yes' Permanent='yes' Vital='yes' RollbackBoundaryBackward='WixDefaultBoundary' LogPathVariable='WixBundleLog_cscript.exe' RollbackLogPathVariable='WixBundleRollbackLog_cscript.exe' DetectCondition='none' InstallArguments='' UninstallArguments='' Uninstallable='yes' RepairArguments='' Repairable='no'><PayloadRef Id='cscript.exe' /><PayloadRef Id='SourceFilePayload' /></ExePackage>", exePackageElements[1].GetTestXml(ignoreAttributesByElementName));
357 + Assert.Equal("<ExePackage Id='credwiz.exe' Cache='keep' CacheId='*' InstallSize='*' Size='*' PerMachine='yes' Permanent='yes' Vital='yes' RollbackBoundaryForward='WixDefaultBoundary' LogPathVariable='WixBundleLog_credwiz.exe' RollbackLogPathVariable='WixBundleRollbackLog_credwiz.exe' DetectCondition='none' InstallArguments='' UninstallArguments='-foo' Uninstallable='yes' RepairArguments='' Repairable='no' Protocol='burn' Bundle='yes'><PayloadRef Id='credwiz.exe' /><PayloadRef Id='SourceFilePayload' /></ExePackage>", exePackageElements[0].GetTestXml(ignoreAttributesByElementName));
358 + Assert.Equal("<ExePackage Id='cscript.exe' Cache='keep' CacheId='*' InstallSize='*' Size='*' PerMachine='yes' Permanent='yes' Vital='yes' RollbackBoundaryBackward='WixDefaultBoundary' LogPathVariable='WixBundleLog_cscript.exe' RollbackLogPathVariable='WixBundleRollbackLog_cscript.exe' DetectCondition='none' InstallArguments='' UninstallArguments='' Uninstallable='yes' RepairArguments='' Repairable='no' Protocol='none' Bundle='yes'><PayloadRef Id='cscript.exe' /><PayloadRef Id='SourceFilePayload' /></ExePackage>", exePackageElements[1].GetTestXml(ignoreAttributesByElementName));
359 }
360 }
361
src/wix/test/WixToolsetTest.CoreIntegration/TestData/BadInput/BundleExePackageWithNetfxProtocol.wxs new
+8
@@ -0,0 +1,8 @@
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
3 + <Fragment>
4 + <PackageGroup Id="BundlePackages">
5 + <ExePackage SourceFile="burn.exe" Bundle="yes" Protocol="netfx4" DetectCondition="none" InstallArguments="/q /norestart" UninstallArguments="/q /norestart" />
6 + </PackageGroup>
7 + </Fragment>
8 +</Wix>
src/wix/test/WixToolsetTest.CoreIntegration/TestData/SharedPayloadsBetweenPackages/SharedPayloadsBetweenPackages.wxs
+2 -2
@@ -2,10 +2,10 @@
2 <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
3 <Fragment>
4 <PackageGroup Id="BundlePackages">
5 - <ExePackage SourceFile="C:\Windows\system32\credwiz.exe" Permanent="yes" DetectCondition="none" UninstallArguments="-foo">
5 + <ExePackage SourceFile="C:\Windows\system32\credwiz.exe" Permanent="yes" DetectCondition="none" UninstallArguments="-foo" Bundle="yes">
6 <PayloadGroupRef Id="SharedPayloads" />
7 </ExePackage>
8 - <ExePackage SourceFile="C:\Windows\system32\cscript.exe" Permanent="yes" DetectCondition="none" UninstallArguments="">
8 + <ExePackage SourceFile="C:\Windows\system32\cscript.exe" Permanent="yes" DetectCondition="none" UninstallArguments="" Bundle="yes" Protocol="none">
9 <PayloadGroupRef Id="SharedPayloads" />
10 </ExePackage>
11 </PackageGroup>