From 7db9a9436d8734d050582afdb3a2dfda21c606e1 Mon Sep 17 00:00:00 2001 From: Bob Arnson Date: Sat, 1 Aug 2026 22:55:27 -0400 Subject: Add CancelWhenDeferred, like FailWhenDeferred. Useful for integration testing packages. --- src/ext/Util/ca/test.cpp | 15 +++++++++++++++ src/ext/Util/ca/utilca.def | 1 + .../WixToolsetTest.Util/TestData/Failures/Package.wxs | 9 +++++++++ .../Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs | 15 +++++++++++++++ src/ext/Util/wixext/UtilCompiler.cs | 9 ++++++++- src/ext/Util/wixlib/UtilExtension_Platform.wxi | 8 ++++++++ src/ext/caDecor.h | 10 ++++++++++ src/ext/caDecor.wxi | 6 ++++++ src/wix/Directory.Build.targets | 2 +- src/xsd/util/CancelWhenDeferred.xsd | 11 +++++++++++ src/xsd/util/order.txt | 1 + 11 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 src/ext/Util/test/WixToolsetTest.Util/TestData/Failures/Package.wxs create mode 100644 src/xsd/util/CancelWhenDeferred.xsd (limited to 'src') diff --git a/src/ext/Util/ca/test.cpp b/src/ext/Util/ca/test.cpp index e9d02ed3..8f1c238b 100644 --- a/src/ext/Util/ca/test.cpp +++ b/src/ext/Util/ca/test.cpp @@ -39,6 +39,21 @@ static LRESULT CALLBACK WndProc( ); +/****************************************************************** +WixCancelWhenDeferred - entry point for WixCancelWhenDeferred + custom action which always cancels when running as a deferred + custom action (otherwise it blindly succeeds). It's useful when + testing the rollback of deferred custom actions: Schedule it + immediately after the rollback/deferred CA pair you're testing + and it will fail, causing your rollback CA to get invoked. +********************************************************************/ +extern "C" UINT __stdcall WixCancelWhenDeferred( + __in MSIHANDLE hInstall +) +{ + return ::MsiGetMode(hInstall, MSIRUNMODE_SCHEDULED) ? ERROR_INSTALL_USEREXIT : ERROR_SUCCESS; +} + /****************************************************************** WixFailWhenDeferred - entry point for WixFailWhenDeferred custom action which always fails when running as a deferred diff --git a/src/ext/Util/ca/utilca.def b/src/ext/Util/ca/utilca.def index 2aeb54f4..f525233d 100644 --- a/src/ext/Util/ca/utilca.def +++ b/src/ext/Util/ca/utilca.def @@ -82,6 +82,7 @@ EXPORTS WixShellExecBinary WixUnelevatedShellExec ; test.cpp + WixCancelWhenDeferred WixFailWhenDeferred WixWaitForEvent ; TouchFile.cpp diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/Failures/Package.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/Failures/Package.wxs new file mode 100644 index 00000000..76975b69 --- /dev/null +++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/Failures/Package.wxs @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs b/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs index b29607c7..1f39601d 100644 --- a/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs +++ b/src/ext/Util/test/WixToolsetTest.Util/UtilExtensionFixture.cs @@ -100,6 +100,21 @@ namespace WixToolsetTest.Util }, results.OrderBy(s => s).ToArray()); } + [TestMethod] + public void CanBuildWithFailures() + { + var folder = TestData.Get(@"TestData\Failures"); + var build = new Builder(folder, typeof(UtilExtensionFactory), new[] { folder }); + + var results = build.BuildAndQuery(BuildX64, "Binary", "CustomAction"); + WixAssert.CompareLineByLine( + [ + "Binary:Wix4UtilCA_X64\t[Binary data]", + "CustomAction:Wix4FailWhenDeferred_X64\t1025\tWix4UtilCA_X64\tWixFailWhenDeferred\t", + "CustomAction:Wix8CancelWhenDeferred_X64\t1025\tWix4UtilCA_X64\tWixCancelWhenDeferred\t", + ], [.. results.OrderBy(s => s)]); + } + [TestMethod] public void CanBuildInternetShortcutInProduct() { diff --git a/src/ext/Util/wixext/UtilCompiler.cs b/src/ext/Util/wixext/UtilCompiler.cs index 919cc49b..1d11f37f 100644 --- a/src/ext/Util/wixext/UtilCompiler.cs +++ b/src/ext/Util/wixext/UtilCompiler.cs @@ -210,6 +210,7 @@ namespace WixToolset.Util break; case "BroadcastEnvironmentChange": case "BroadcastSettingChange": + case "CancelWhenDeferred": case "CheckRebootRequired": case "ExitEarlyWithSuccess": case "FailWhenDeferred": @@ -328,6 +329,7 @@ namespace WixToolset.Util { case "BroadcastEnvironmentChange": case "BroadcastSettingChange": + case "CancelWhenDeferred": case "CheckRebootRequired": case "ExitEarlyWithSuccess": case "FailWhenDeferred": @@ -358,6 +360,7 @@ namespace WixToolset.Util return; } + var prefix = "Wix4"; var customAction = element.Name.LocalName; switch (element.Name.LocalName) { @@ -370,6 +373,10 @@ namespace WixToolset.Util case "WaitForEventDeferred": //default: customAction = element.Name.LocalName; break; + case "CancelWhenDeferred": + prefix = "Wix8"; + //default: customAction = element.Name.LocalName; + break; case "QueryWindowsDirectories": customAction = "QueryOsDirs"; break; @@ -400,7 +407,7 @@ namespace WixToolset.Util this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); - this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4" + customAction, this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, prefix + customAction, this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64); } /// diff --git a/src/ext/Util/wixlib/UtilExtension_Platform.wxi b/src/ext/Util/wixlib/UtilExtension_Platform.wxi index d28c8df9..6316eaf1 100644 --- a/src/ext/Util/wixlib/UtilExtension_Platform.wxi +++ b/src/ext/Util/wixlib/UtilExtension_Platform.wxi @@ -4,6 +4,14 @@ + + + + + + + + diff --git a/src/ext/caDecor.h b/src/ext/caDecor.h index 4a09e075..9484d74c 100644 --- a/src/ext/caDecor.h +++ b/src/ext/caDecor.h @@ -31,3 +31,13 @@ #else #define CUSTOM_ACTION_DECORATION6(f) L"Wix6" f L"_X86" #endif + +#if defined(_M_ARM64) +#define CUSTOM_ACTION_DECORATION8(f) L"Wix8" f L"_A64" +#elif defined(_M_AMD64) +#define CUSTOM_ACTION_DECORATION8(f) L"Wix8" f L"_X64" +#elif defined(_M_ARM) +#define CUSTOM_ACTION_DECORATION8(f) L"Wix8" f L"_ARM" +#else +#define CUSTOM_ACTION_DECORATION8(f) L"Wix8" f L"_X86" +#endif diff --git a/src/ext/caDecor.wxi b/src/ext/caDecor.wxi index 236b2154..c92af980 100644 --- a/src/ext/caDecor.wxi +++ b/src/ext/caDecor.wxi @@ -19,6 +19,12 @@ + + + + + + diff --git a/src/wix/Directory.Build.targets b/src/wix/Directory.Build.targets index 78b83e60..28749932 100644 --- a/src/wix/Directory.Build.targets +++ b/src/wix/Directory.Build.targets @@ -4,7 +4,7 @@ - + diff --git a/src/xsd/util/CancelWhenDeferred.xsd b/src/xsd/util/CancelWhenDeferred.xsd new file mode 100644 index 00000000..062be147 --- /dev/null +++ b/src/xsd/util/CancelWhenDeferred.xsd @@ -0,0 +1,11 @@ + + + Schedules the CancelWhenDeferred custom action for the current platform. + + + + + + + + \ No newline at end of file diff --git a/src/xsd/util/order.txt b/src/xsd/util/order.txt index 63f854ae..1181e97a 100644 --- a/src/xsd/util/order.txt +++ b/src/xsd/util/order.txt @@ -33,6 +33,7 @@ element|XmlFile element|XmlConfig element|BroadcastEnvironmentChange element|BroadcastSettingChange +element|CancelWhenDeferred element|CheckRebootRequired element|ExitEarlyWithSuccess element|FailWhenDeferred -- cgit v1.2.3-55-g6feb