@joebigelow / wix / commits / 13292da7

Warn about unsuffixed custom action ids.

Fixes https://github.com/wixtoolset/issues/issues/7018.

Bob Arnson committed Nov 16, 2022 at 20:27 UTC 13292da793c9e0792d3ecd86974304b8b2a51d7a
2 files changed +110 -1
src/wix/WixToolset.Converters/WixConverter.cs
+78 -1
@@ -78,6 +78,7 @@ namespace WixToolset.Converters
78 private static readonly XName BundleCustomDataElementName = WixNamespace + "BundleCustomData";
79 private static readonly XName BundleCustomDataRefElementName = WixNamespace + "BundleCustomDataRef";
80 private static readonly XName BundleElementElementName = WixNamespace + "BundleElement";
81 + private static readonly XName CustomElementName = WixNamespace + "Custom";
82 private static readonly XName CustomTableElementName = WixNamespace + "CustomTable";
83 private static readonly XName CustomTableRefElementName = WixNamespace + "CustomTableRef";
84 private static readonly XName CatalogElementName = WixNamespace + "Catalog";
@@ -97,7 +98,6 @@ namespace WixToolset.Converters
98 private static readonly XName FileElementName = WixNamespace + "File";
99 private static readonly XName FragmentElementName = WixNamespace + "Fragment";
100 private static readonly XName FirewallRemoteAddressElementName = WixFirewallNamespace + "RemoteAddress";
100 - private static readonly XName GetCapabilitiesElementName = WixFirewallNamespace + "GetCapabilities";
101 private static readonly XName LaunchElementName = WixNamespace + "Launch";
102 private static readonly XName LevelElementName = WixNamespace + "Level";
103 private static readonly XName ExePackageElementName = WixNamespace + "ExePackage";
@@ -196,6 +196,65 @@ namespace WixToolset.Converters
196 { "http://schemas.microsoft.com/wix/2006/WixUnit", "http://wixtoolset.org/schemas/v4/wixunit" },
197 };
198
199 + private static readonly Dictionary<string, string> CustomActionIdsWithPlatformSuffix = new Dictionary<string, string>()
200 + {
201 + { "ConfigureComPlusUninstall", "Wix4ConfigureComPlusUninstall_<PlatformSuffix>" },
202 + { "ConfigureComPlusInstall", "Wix4ConfigureComPlusInstall_<PlatformSuffix>" },
203 + { "WixDependencyRequire", "Wix4DependencyRequire_<PlatformSuffix>" },
204 + { "WixDependencyCheck", "Wix4DependencyCheck_<PlatformSuffix>" },
205 + { "WixQueryDirectXCaps", "Wix4QueryDirectXCaps_<PlatformSuffix>" },
206 + { "WixSchedFirewallExceptionsUninstall", "Wix4SchedFirewallExceptionsUninstall_<PlatformSuffix>" },
207 + { "WixSchedFirewallExceptionsInstall", "Wix4SchedFirewallExceptionsInstall_<PlatformSuffix>" },
208 + { "WixSchedHttpUrlReservationsUninstall", "Wix4SchedHttpUrlReservationsUninstall_<PlatformSuffix>" },
209 + { "WixSchedHttpUrlReservationsInstall", "Wix4SchedHttpUrlReservationsInstall_<PlatformSuffix>" },
210 + { "ConfigureIIs", "Wix4ConfigureIIs_<PlatformSuffix>" },
211 + { "UninstallCertificates", "Wix4UninstallCertificates_<PlatformSuffix>" },
212 + { "InstallCertificates", "Wix4_<PlatformSuffix>" },
213 + { "MessageQueuingUninstall", "Wix4MessageQueuingUninstall_<PlatformSuffix>" },
214 + { "MessageQueuingInstall", "Wix4_MessageQueuingInstall<PlatformSuffix>" },
215 + { "NetFxScheduleNativeImage", "Wix4NetFxScheduleNativeImage_<PlatformSuffix>" },
216 + { "NetFxExecuteNativeImageCommitUninstall", "Wix4NetFxExecuteNativeImageCommitUninstall_<PlatformSuffix>" },
217 + { "NetFxExecuteNativeImageUninstall", "Wix4NetFxExecuteNativeImageUninstall_<PlatformSuffix>" },
218 + { "NetFxExecuteNativeImageCommitInstall", "Wix4NetFxExecuteNativeImageCommitInstall_<PlatformSuffix>" },
219 + { "NetFxExecuteNativeImageInstall", "Wix4NetFxExecuteNativeImageInstall_<PlatformSuffix>" },
220 + { "UninstallSqlData", "Wix4UninstallSqlData_<PlatformSuffix>" },
221 + { "InstallSqlData", "Wix4InstallSqlData_<PlatformSuffix>" },
222 + { "WixCheckRebootRequired", "Wix4CheckRebootRequired_<PlatformSuffix>" },
223 + { "WixCloseApplications", "Wix4CloseApplications_<PlatformSuffix>" },
224 + { "WixRegisterRestartResources", "Wix4RegisterRestartResources_<PlatformSuffix>" },
225 + { "ConfigureUsers", "Wix4ConfigureUsers_<PlatformSuffix>" },
226 + { "ConfigureSmbInstall", "Wix4ConfigureSmbInstall_<PlatformSuffix>" },
227 + { "ConfigureSmbUninstall", "Wix4ConfigureSmbUninstall_<PlatformSuffix>" },
228 + { "InstallPerfCounterData", "Wix4InstallPerfCounterData_<PlatformSuffix>" },
229 + { "UninstallPerfCounterData", "Wix4UninstallPerfCounterData_<PlatformSuffix>" },
230 + { "ConfigurePerfmonInstall", "Wix4ConfigurePerfmonInstall_<PlatformSuffix>" },
231 + { "ConfigurePerfmonUninstall", "Wix4ConfigurePerfmonUninstall_<PlatformSuffix>" },
232 + { "ConfigurePerfmonManifestRegister", "Wix4ConfigurePerfmonManifestRegister_<PlatformSuffix>" },
233 + { "ConfigurePerfmonManifestUnregister", "Wix4ConfigurePerfmonManifestUnregister_<PlatformSuffix>" },
234 + { "ConfigureEventManifestRegister", "Wix4ConfigureEventManifestRegister_<PlatformSuffix>" },
235 + { "ConfigureEventManifestUnregister", "Wix4ConfigureEventManifestUnregister_<PlatformSuffix>" },
236 + { "SchedServiceConfig", "Wix4SchedServiceConfig_<PlatformSuffix>" },
237 + { "SchedXmlFile", "Wix4SchedXmlFile_<PlatformSuffix>" },
238 + { "SchedXmlConfig", "Wix4SchedXmlConfig_<PlatformSuffix>" },
239 + { "WixSchedInternetShortcuts", "Wix4SchedInternetShortcuts_<PlatformSuffix>" },
240 + { "WixRollbackInternetShortcuts", "Wix4RollbackInternetShortcuts_<PlatformSuffix>" },
241 + { "WixCreateInternetShortcuts", "Wix4CreateInternetShortcuts_<PlatformSuffix>" },
242 + { "WixQueryOsInfo", "Wix4QueryOsInfo_<PlatformSuffix>" },
243 + { "WixQueryOsDirs", "Wix4QueryOsDirs_<PlatformSuffix>" },
244 + { "WixQueryOsWellKnownSID", "Wix4QueryOsWellKnownSID_<PlatformSuffix>" },
245 + { "WixQueryOsDriverInfo", "Wix4QueryOsDriverInfo_<PlatformSuffix>" },
246 + { "WixQueryNativeMachine", "Wix4QueryNativeMachine_<PlatformSuffix>" },
247 + { "WixFailWhenDeferred", "Wix4FailWhenDeferred_<PlatformSuffix>" },
248 + { "WixWaitForEvent", "Wix4WaitForEvent_<PlatformSuffix>" },
249 + { "WixWaitForEventDeferred", "Wix4WaitForEventDeferred_<PlatformSuffix>" },
250 + { "WixExitEarlyWithSuccess", "Wix4ExitEarlyWithSuccess_<PlatformSuffix>" },
251 + { "WixBroadcastSettingChange", "Wix4BroadcastSettingChange_<PlatformSuffix>" },
252 + { "WixBroadcastEnvironmentChange", "Wix4BroadcastEnvironmentChange_<PlatformSuffix>" },
253 + { "SchedSecureObjects", "Wix4SchedSecureObjects_<PlatformSuffix>" },
254 + { "SchedSecureObjectsRollback", "Wix4SchedSecureObjectsRollback_<PlatformSuffix>" },
255 + { "VSFindInstances", "Wix4VSFindInstances_<PlatformSuffix>" },
256 + };
257 +
258 private readonly Dictionary<XName, Action<XElement>> ConvertElementMapping;
259 private readonly Regex DeprecatedPrefixRegex = new Regex(@"(?<=(^|[^\$])(\$\$)*)\$(?=\(loc\.[^.].*\))",
260 RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture);
@@ -224,6 +283,7 @@ namespace WixToolset.Converters
283 { WixConverter.ColumnElementName, this.ConvertColumnElement },
284 { WixConverter.ComponentElementName, this.ConvertComponentElement },
285 { WixConverter.ControlElementName, this.ConvertControlElement },
286 + { WixConverter.CustomElementName, this.ConvertCustomElement },
287 { WixConverter.CustomActionElementName, this.ConvertCustomActionElement },
288 { WixConverter.CustomTableElementName, this.ConvertCustomTableElement },
289 { WixConverter.DataElementName, this.ConvertDataElement },
@@ -840,6 +900,18 @@ namespace WixToolset.Converters
900 }
901 }
902
903 + private void ConvertCustomElement(XElement element)
904 + {
905 + var actionId = element.Attribute("Action")?.Value;
906 +
907 + if (actionId != null
908 + && CustomActionIdsWithPlatformSuffix.TryGetValue(actionId, out var replacementId))
909 + {
910 + this.OnError(ConverterTestType.CustomActionIdsIncludePlatformSuffix, element,
911 + $"Custom action ids have changed in WiX v4 extensions to support platform-specific custom actions. The platform is applied as a suffix: _X86, _X64, _A64 (Arm64). When manually rescheduling custom action '{actionId}', you must use the new custom action id '{replacementId}'.");
912 + }
913 + }
914 +
915 private void ConvertCustomTableElement(XElement element)
916 {
917 var bootstrapperApplicationData = element.Attribute("BootstrapperApplicationData");
@@ -3056,6 +3128,11 @@ namespace WixToolset.Converters
3128 /// Namespace should be defined on the root. The '{0}' namespace was move to the root element.
3129 /// </summary>
3130 MoveNamespacesToRoot,
3131 +
3132 + /// <summary>
3133 + /// Custom action ids have changed in WiX v4 extensions. Because WiX v4 has platform-specific custom actions, the platform is applied as a suffix: _X86, _X64, _A64 (Arm64). When manually rescheduling custom actions, you must use the new custom action id, with platform suffix.
3134 + /// </summary>
3135 + CustomActionIdsIncludePlatformSuffix,
3136 }
3137 }
3138 }
src/wix/test/WixToolsetTest.Converters/ConverterFixture.cs
+32
@@ -512,5 +512,37 @@ namespace WixToolsetTest.Converters
512 Assert.Equal(3, errors);
513 WixAssert.CompareLineByLine(expected, actual);
514 }
515 +
516 + [Fact]
517 + public void CantConvertStandardCustomActionRescheduling()
518 + {
519 + var parse = String.Join(Environment.NewLine,
520 + "<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>",
521 + " <InstallExecuteSequence>",
522 + " <Custom Action='WixCloseApplications' Before='StopServices' />",
523 + " </InstallExecuteSequence>",
524 + "</Wix>");
525 +
526 + var expected = new[]
527 + {
528 + "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\">",
529 + " <InstallExecuteSequence>",
530 + " <Custom Action=\"WixCloseApplications\" Before=\"StopServices\" />",
531 + " </InstallExecuteSequence>",
532 + "</Wix>",
533 + };
534 +
535 + var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
536 +
537 + var messaging = new MockMessaging();
538 + var converter = new WixConverter(messaging, 2, null, null);
539 +
540 + var errors = converter.ConvertDocument(document);
541 +
542 + var actual = UnformattedDocumentLines(document);
543 +
544 + Assert.Equal(2, errors);
545 + WixAssert.CompareLineByLine(expected, actual);
546 + }
547 }
548 }