@joebigelow / wix-1 / commits / 05d9529a

Also use EnsureTable to schedule standard actions.

Fixes https://github.com/wixtoolset/issues/issues/8632 Fixes https://github.com/wixtoolset/issues/issues/8199

Bob Arnson committed Aug 25, 2024 at 19:13 UTC 05d9529abdee99372e3b99808f8fed04c755ae95
3 files changed +244 -156
src/wix/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs
+204 -156
@@ -4,7 +4,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
4 {
5 using System;
6 using System.Collections.Generic;
7 - using System.Globalization;
7 using System.Linq;
8 using WixToolset.Data;
9 using WixToolset.Data.Symbols;
@@ -30,6 +29,42 @@ namespace WixToolset.Core.WindowsInstaller.Bind
29
30 private Dictionary<string, RelativeActions> RelativeActionsForActions { get; }
31
32 + public Dictionary<string, SymbolDefinitionType> SymbolTypeForTable { get; } = new Dictionary<string, SymbolDefinitionType>
33 + {
34 + { "AppSearch", SymbolDefinitionType.AppSearch },
35 + { "CCPSearch", SymbolDefinitionType.CCPSearch },
36 + { "Class", SymbolDefinitionType.Class },
37 + { "Complus", SymbolDefinitionType.Complus},
38 + { "CreateFolder", SymbolDefinitionType.CreateFolder },
39 + { "DuplicateFile", SymbolDefinitionType.DuplicateFile },
40 + { "Environment", SymbolDefinitionType.Environment },
41 + { "Extension", SymbolDefinitionType.Extension },
42 + { "File", SymbolDefinitionType.File },
43 + { "IniFile", SymbolDefinitionType.IniFile },
44 + { "IsolatedComponent", SymbolDefinitionType.IsolatedComponent },
45 + { "LaunchCondition", SymbolDefinitionType.LaunchCondition },
46 + { "MIME", SymbolDefinitionType.MIME },
47 + { "MoveFile", SymbolDefinitionType.MoveFile },
48 + { "MsiAssembly", SymbolDefinitionType.Assembly },
49 + { "MsiAssemblyName", SymbolDefinitionType.Assembly },
50 + { "MsiServiceConfig", SymbolDefinitionType.LaunchCondition },
51 + { "MsiServiceConfigFailureActions", SymbolDefinitionType.MsiServiceConfigFailureActions },
52 + { "ODBCAttribute", SymbolDefinitionType.ODBCAttribute },
53 + { "ODBCDataSource", SymbolDefinitionType.ODBCDataSource },
54 + { "ODBCDriver", SymbolDefinitionType.ODBCDriver },
55 + { "ODBCTranslator", SymbolDefinitionType.ODBCTranslator },
56 + { "ODBCSourceAttribute", SymbolDefinitionType.ODBCSourceAttribute },
57 + { "PublishComponent", SymbolDefinitionType.PublishComponent },
58 + { "Registry", SymbolDefinitionType.Registry },
59 + { "RemoveRegistry", SymbolDefinitionType.RemoveRegistry },
60 + { "RemoveFile", SymbolDefinitionType.RemoveFile },
61 + { "ServiceControl", SymbolDefinitionType.ServiceControl },
62 + { "ServiceInstall", SymbolDefinitionType.ServiceInstall },
63 + { "Shortcut", SymbolDefinitionType.Shortcut },
64 + { "TypeLib", SymbolDefinitionType.TypeLib },
65 + { "Upgrade", SymbolDefinitionType.Upgrade },
66 + };
67 +
68 public void Execute()
69 {
70 var requiredActionSymbols = new Dictionary<string, WixActionSymbol>();
@@ -131,7 +166,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
166
167 // A dictionary used for detecting cyclic references among action symbols.
168 var firstReference = new Dictionary<WixActionSymbol, WixActionSymbol>();
134 -
169 +
170 // Build up dependency trees of the relatively scheduled actions.
171 // Use ToList() to create a copy of the required action symbols so that new symbols can
172 // be added while enumerating.
@@ -396,165 +431,179 @@ namespace WixToolset.Core.WindowsInstaller.Bind
431 // Gather the required actions for each symbol type.
432 foreach (var symbolType in this.Section.Symbols.Select(t => t.Definition.Type).Distinct())
433 {
399 - switch (symbolType)
434 + this.GetActionsForSymbolType(symbolType, set);
435 + }
436 +
437 + // Gather the required actions for each ensured table.
438 + foreach (var ensureTable in this.Section.Symbols.OfType<WixEnsureTableSymbol>())
439 + {
440 + if (this.SymbolTypeForTable.TryGetValue(ensureTable.Table, out var symbolType))
441 {
401 - case SymbolDefinitionType.AppSearch:
402 - set.Add("InstallExecuteSequence/AppSearch");
403 - set.Add("InstallUISequence/AppSearch");
404 - break;
405 - case SymbolDefinitionType.CCPSearch:
406 - set.Add("InstallExecuteSequence/AppSearch");
407 - set.Add("InstallExecuteSequence/CCPSearch");
408 - set.Add("InstallExecuteSequence/RMCCPSearch");
409 - set.Add("InstallUISequence/AppSearch");
410 - set.Add("InstallUISequence/CCPSearch");
411 - set.Add("InstallUISequence/RMCCPSearch");
412 - break;
413 - case SymbolDefinitionType.Class:
414 - set.Add("AdvertiseExecuteSequence/RegisterClassInfo");
415 - set.Add("InstallExecuteSequence/RegisterClassInfo");
416 - set.Add("InstallExecuteSequence/UnregisterClassInfo");
417 - break;
418 - case SymbolDefinitionType.Complus:
419 - set.Add("InstallExecuteSequence/RegisterComPlus");
420 - set.Add("InstallExecuteSequence/UnregisterComPlus");
421 - break;
422 - case SymbolDefinitionType.Component:
423 - case SymbolDefinitionType.CreateFolder:
424 - set.Add("InstallExecuteSequence/CreateFolders");
425 - set.Add("InstallExecuteSequence/RemoveFolders");
426 - break;
427 - case SymbolDefinitionType.DuplicateFile:
428 - set.Add("InstallExecuteSequence/DuplicateFiles");
429 - set.Add("InstallExecuteSequence/RemoveDuplicateFiles");
430 - break;
431 - case SymbolDefinitionType.Environment:
432 - set.Add("InstallExecuteSequence/WriteEnvironmentStrings");
433 - set.Add("InstallExecuteSequence/RemoveEnvironmentStrings");
434 - break;
435 - case SymbolDefinitionType.Extension:
436 - set.Add("AdvertiseExecuteSequence/RegisterExtensionInfo");
437 - set.Add("InstallExecuteSequence/RegisterExtensionInfo");
438 - set.Add("InstallExecuteSequence/UnregisterExtensionInfo");
439 - break;
440 - case SymbolDefinitionType.File:
441 - set.Add("InstallExecuteSequence/InstallFiles");
442 - set.Add("InstallExecuteSequence/RemoveFiles");
443 -
444 - var foundFont = false;
445 - var foundSelfReg = false;
446 - var foundBindPath = false;
447 - foreach (var file in this.Section.Symbols.OfType<FileSymbol>())
448 - {
449 - // Note that TrueType fonts are denoted by the empty string in the FontTitle
450 - // field. So, non-null means a font is present.
451 - if (!foundFont && file.FontTitle != null)
452 - {
453 - set.Add("InstallExecuteSequence/RegisterFonts");
454 - set.Add("InstallExecuteSequence/UnregisterFonts");
455 - foundFont = true;
456 - }
442 + this.GetActionsForSymbolType(symbolType, set);
443 + }
444 + }
445
458 - if (!foundSelfReg && file.SelfRegCost.HasValue)
459 - {
460 - set.Add("InstallExecuteSequence/SelfRegModules");
461 - set.Add("InstallExecuteSequence/SelfUnregModules");
462 - foundSelfReg = true;
463 - }
446 + return set;
447 + }
448
465 - if (!foundBindPath && !String.IsNullOrEmpty(file.BindPath))
466 - {
467 - set.Add("InstallExecuteSequence/BindImage");
468 - foundBindPath = true;
469 - }
449 + private void GetActionsForSymbolType(SymbolDefinitionType symbolType, HashSet<string> set)
450 + {
451 + switch (symbolType)
452 + {
453 + case SymbolDefinitionType.AppSearch:
454 + set.Add("InstallExecuteSequence/AppSearch");
455 + set.Add("InstallUISequence/AppSearch");
456 + break;
457 + case SymbolDefinitionType.CCPSearch:
458 + set.Add("InstallExecuteSequence/AppSearch");
459 + set.Add("InstallExecuteSequence/CCPSearch");
460 + set.Add("InstallExecuteSequence/RMCCPSearch");
461 + set.Add("InstallUISequence/AppSearch");
462 + set.Add("InstallUISequence/CCPSearch");
463 + set.Add("InstallUISequence/RMCCPSearch");
464 + break;
465 + case SymbolDefinitionType.Class:
466 + set.Add("AdvertiseExecuteSequence/RegisterClassInfo");
467 + set.Add("InstallExecuteSequence/RegisterClassInfo");
468 + set.Add("InstallExecuteSequence/UnregisterClassInfo");
469 + break;
470 + case SymbolDefinitionType.Complus:
471 + set.Add("InstallExecuteSequence/RegisterComPlus");
472 + set.Add("InstallExecuteSequence/UnregisterComPlus");
473 + break;
474 + case SymbolDefinitionType.Component:
475 + case SymbolDefinitionType.CreateFolder:
476 + set.Add("InstallExecuteSequence/CreateFolders");
477 + set.Add("InstallExecuteSequence/RemoveFolders");
478 + break;
479 + case SymbolDefinitionType.DuplicateFile:
480 + set.Add("InstallExecuteSequence/DuplicateFiles");
481 + set.Add("InstallExecuteSequence/RemoveDuplicateFiles");
482 + break;
483 + case SymbolDefinitionType.Environment:
484 + set.Add("InstallExecuteSequence/WriteEnvironmentStrings");
485 + set.Add("InstallExecuteSequence/RemoveEnvironmentStrings");
486 + break;
487 + case SymbolDefinitionType.Extension:
488 + set.Add("AdvertiseExecuteSequence/RegisterExtensionInfo");
489 + set.Add("InstallExecuteSequence/RegisterExtensionInfo");
490 + set.Add("InstallExecuteSequence/UnregisterExtensionInfo");
491 + break;
492 + case SymbolDefinitionType.File:
493 + set.Add("InstallExecuteSequence/InstallFiles");
494 + set.Add("InstallExecuteSequence/RemoveFiles");
495 +
496 + var foundFont = false;
497 + var foundSelfReg = false;
498 + var foundBindPath = false;
499 + foreach (var file in this.Section.Symbols.OfType<FileSymbol>())
500 + {
501 + // Note that TrueType fonts are denoted by the empty string in the FontTitle
502 + // field. So, non-null means a font is present.
503 + if (!foundFont && file.FontTitle != null)
504 + {
505 + set.Add("InstallExecuteSequence/RegisterFonts");
506 + set.Add("InstallExecuteSequence/UnregisterFonts");
507 + foundFont = true;
508 }
471 - break;
472 - case SymbolDefinitionType.IniFile:
473 - set.Add("InstallExecuteSequence/WriteIniValues");
474 - set.Add("InstallExecuteSequence/RemoveIniValues");
475 - break;
476 - case SymbolDefinitionType.IsolatedComponent:
477 - set.Add("InstallExecuteSequence/IsolateComponents");
478 - break;
479 - case SymbolDefinitionType.LaunchCondition:
480 - set.Add("InstallExecuteSequence/LaunchConditions");
481 - set.Add("InstallUISequence/LaunchConditions");
482 - break;
483 - case SymbolDefinitionType.MIME:
484 - set.Add("AdvertiseExecuteSequence/RegisterMIMEInfo");
485 - set.Add("InstallExecuteSequence/RegisterMIMEInfo");
486 - set.Add("InstallExecuteSequence/UnregisterMIMEInfo");
487 - break;
488 - case SymbolDefinitionType.MoveFile:
489 - set.Add("InstallExecuteSequence/MoveFiles");
490 - break;
491 - case SymbolDefinitionType.Assembly:
492 - set.Add("AdvertiseExecuteSequence/MsiPublishAssemblies");
493 - set.Add("InstallExecuteSequence/MsiPublishAssemblies");
494 - set.Add("InstallExecuteSequence/MsiUnpublishAssemblies");
495 - break;
496 - case SymbolDefinitionType.MsiServiceConfig:
497 - case SymbolDefinitionType.MsiServiceConfigFailureActions:
498 - set.Add("InstallExecuteSequence/MsiConfigureServices");
499 - break;
500 - case SymbolDefinitionType.ODBCDataSource:
501 - case SymbolDefinitionType.ODBCTranslator:
502 - case SymbolDefinitionType.ODBCDriver:
503 - set.Add("InstallExecuteSequence/SetODBCFolders");
504 - set.Add("InstallExecuteSequence/InstallODBC");
505 - set.Add("InstallExecuteSequence/RemoveODBC");
506 - break;
507 - case SymbolDefinitionType.ProgId:
508 - set.Add("AdvertiseExecuteSequence/RegisterProgIdInfo");
509 - set.Add("InstallExecuteSequence/RegisterProgIdInfo");
510 - set.Add("InstallExecuteSequence/UnregisterProgIdInfo");
511 - break;
512 - case SymbolDefinitionType.PublishComponent:
513 - set.Add("AdvertiseExecuteSequence/PublishComponents");
514 - set.Add("InstallExecuteSequence/PublishComponents");
515 - set.Add("InstallExecuteSequence/UnpublishComponents");
516 - break;
517 - case SymbolDefinitionType.Registry:
518 - case SymbolDefinitionType.RemoveRegistry:
519 - set.Add("InstallExecuteSequence/WriteRegistryValues");
520 - set.Add("InstallExecuteSequence/RemoveRegistryValues");
521 - break;
522 - case SymbolDefinitionType.RemoveFile:
523 - set.Add("InstallExecuteSequence/RemoveFiles");
524 - break;
525 - case SymbolDefinitionType.ServiceControl:
526 - set.Add("InstallExecuteSequence/StartServices");
527 - set.Add("InstallExecuteSequence/StopServices");
528 - set.Add("InstallExecuteSequence/DeleteServices");
529 - break;
530 - case SymbolDefinitionType.ServiceInstall:
531 - set.Add("InstallExecuteSequence/InstallServices");
532 - break;
533 - case SymbolDefinitionType.Shortcut:
534 - set.Add("AdvertiseExecuteSequence/CreateShortcuts");
535 - set.Add("InstallExecuteSequence/CreateShortcuts");
536 - set.Add("InstallExecuteSequence/RemoveShortcuts");
537 - break;
538 - case SymbolDefinitionType.TypeLib:
539 - set.Add("InstallExecuteSequence/RegisterTypeLibraries");
540 - set.Add("InstallExecuteSequence/UnregisterTypeLibraries");
541 - break;
542 - case SymbolDefinitionType.Upgrade:
543 - set.Add("InstallExecuteSequence/FindRelatedProducts");
544 - set.Add("InstallUISequence/FindRelatedProducts");
545 -
546 - // Only add the MigrateFeatureStates action if MigrateFeature attribute is set on
547 - // at least one UpgradeVersion element.
548 - if (this.Section.Symbols.OfType<UpgradeSymbol>().Any(t => t.MigrateFeatures))
509 +
510 + if (!foundSelfReg && file.SelfRegCost.HasValue)
511 {
550 - set.Add("InstallExecuteSequence/MigrateFeatureStates");
551 - set.Add("InstallUISequence/MigrateFeatureStates");
512 + set.Add("InstallExecuteSequence/SelfRegModules");
513 + set.Add("InstallExecuteSequence/SelfUnregModules");
514 + foundSelfReg = true;
515 }
553 - break;
554 - }
555 - }
516
557 - return set;
517 + if (!foundBindPath && !String.IsNullOrEmpty(file.BindPath))
518 + {
519 + set.Add("InstallExecuteSequence/BindImage");
520 + foundBindPath = true;
521 + }
522 + }
523 + break;
524 + case SymbolDefinitionType.IniFile:
525 + set.Add("InstallExecuteSequence/WriteIniValues");
526 + set.Add("InstallExecuteSequence/RemoveIniValues");
527 + break;
528 + case SymbolDefinitionType.IsolatedComponent:
529 + set.Add("InstallExecuteSequence/IsolateComponents");
530 + break;
531 + case SymbolDefinitionType.LaunchCondition:
532 + set.Add("InstallExecuteSequence/LaunchConditions");
533 + set.Add("InstallUISequence/LaunchConditions");
534 + break;
535 + case SymbolDefinitionType.MIME:
536 + set.Add("AdvertiseExecuteSequence/RegisterMIMEInfo");
537 + set.Add("InstallExecuteSequence/RegisterMIMEInfo");
538 + set.Add("InstallExecuteSequence/UnregisterMIMEInfo");
539 + break;
540 + case SymbolDefinitionType.MoveFile:
541 + set.Add("InstallExecuteSequence/MoveFiles");
542 + break;
543 + case SymbolDefinitionType.Assembly:
544 + set.Add("AdvertiseExecuteSequence/MsiPublishAssemblies");
545 + set.Add("InstallExecuteSequence/MsiPublishAssemblies");
546 + set.Add("InstallExecuteSequence/MsiUnpublishAssemblies");
547 + break;
548 + case SymbolDefinitionType.MsiServiceConfig:
549 + case SymbolDefinitionType.MsiServiceConfigFailureActions:
550 + set.Add("InstallExecuteSequence/MsiConfigureServices");
551 + break;
552 + case SymbolDefinitionType.ODBCDataSource:
553 + case SymbolDefinitionType.ODBCTranslator:
554 + case SymbolDefinitionType.ODBCDriver:
555 + set.Add("InstallExecuteSequence/SetODBCFolders");
556 + set.Add("InstallExecuteSequence/InstallODBC");
557 + set.Add("InstallExecuteSequence/RemoveODBC");
558 + break;
559 + case SymbolDefinitionType.ProgId:
560 + set.Add("AdvertiseExecuteSequence/RegisterProgIdInfo");
561 + set.Add("InstallExecuteSequence/RegisterProgIdInfo");
562 + set.Add("InstallExecuteSequence/UnregisterProgIdInfo");
563 + break;
564 + case SymbolDefinitionType.PublishComponent:
565 + set.Add("AdvertiseExecuteSequence/PublishComponents");
566 + set.Add("InstallExecuteSequence/PublishComponents");
567 + set.Add("InstallExecuteSequence/UnpublishComponents");
568 + break;
569 + case SymbolDefinitionType.Registry:
570 + case SymbolDefinitionType.RemoveRegistry:
571 + set.Add("InstallExecuteSequence/WriteRegistryValues");
572 + set.Add("InstallExecuteSequence/RemoveRegistryValues");
573 + break;
574 + case SymbolDefinitionType.RemoveFile:
575 + set.Add("InstallExecuteSequence/RemoveFiles");
576 + break;
577 + case SymbolDefinitionType.ServiceControl:
578 + set.Add("InstallExecuteSequence/StartServices");
579 + set.Add("InstallExecuteSequence/StopServices");
580 + set.Add("InstallExecuteSequence/DeleteServices");
581 + break;
582 + case SymbolDefinitionType.ServiceInstall:
583 + set.Add("InstallExecuteSequence/InstallServices");
584 + break;
585 + case SymbolDefinitionType.Shortcut:
586 + set.Add("AdvertiseExecuteSequence/CreateShortcuts");
587 + set.Add("InstallExecuteSequence/CreateShortcuts");
588 + set.Add("InstallExecuteSequence/RemoveShortcuts");
589 + break;
590 + case SymbolDefinitionType.TypeLib:
591 + set.Add("InstallExecuteSequence/RegisterTypeLibraries");
592 + set.Add("InstallExecuteSequence/UnregisterTypeLibraries");
593 + break;
594 + case SymbolDefinitionType.Upgrade:
595 + set.Add("InstallExecuteSequence/FindRelatedProducts");
596 + set.Add("InstallUISequence/FindRelatedProducts");
597 +
598 + // Only add the MigrateFeatureStates action if MigrateFeature attribute is set on
599 + // at least one UpgradeVersion element.
600 + if (this.Section.Symbols.OfType<UpgradeSymbol>().Any(t => t.MigrateFeatures))
601 + {
602 + set.Add("InstallExecuteSequence/MigrateFeatureStates");
603 + set.Add("InstallUISequence/MigrateFeatureStates");
604 + }
605 + break;
606 + }
607 }
608
609 /// <summary>
@@ -661,8 +710,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
710
711 return parentActionSymbol;
712 }
664 -
665 -
713 +
714 private RelativeActions GetRelativeActions(WixActionSymbol action)
715 {
716 if (!this.RelativeActionsForActions.TryGetValue(action.Id.Id, out var relativeActions))
src/wix/test/WixToolsetTest.CoreIntegration/MsiQueryFixture.cs
+33
@@ -980,5 +980,38 @@ namespace WixToolsetTest.CoreIntegration
980 }, results);
981 }
982 }
983 +
984 + [Fact]
985 + public void EnsureTableSchedulesAppropriateStandardActions()
986 + {
987 + var folder = TestData.Get(@"TestData\EnsureTable");
988 +
989 + using (var fs = new DisposableFileSystem())
990 + {
991 + var baseFolder = fs.GetFolder();
992 + var intermediateFolder = Path.Combine(baseFolder, "obj");
993 + var msiPath = Path.Combine(baseFolder, @"bin\test.msi");
994 +
995 + var result = WixRunner.Execute(new[]
996 + {
997 + "build",
998 + Path.Combine(folder, "StandardActions.wxs"),
999 + "-intermediateFolder", intermediateFolder,
1000 + "-o", msiPath
1001 + });
1002 +
1003 + result.AssertSuccess();
1004 +
1005 + var results = Query.QueryDatabase(msiPath, new[] { "InstallExecuteSequence" });
1006 + WixAssert.CompareLineByLine(new[]
1007 + {
1008 + "InstallExecuteSequence:AppSearch\t\t50",
1009 + "InstallExecuteSequence:CCPSearch\tNOT Installed\t500",
1010 + "InstallExecuteSequence:FileCost\t\t900",
1011 + "InstallExecuteSequence:RemoveFiles\t\t3500",
1012 + "InstallExecuteSequence:RMCCPSearch\tNOT Installed\t600",
1013 + }, results.Where(l => l.Contains("Search") || l.Contains("File")).ToArray());
1014 + }
1015 + }
1016 }
1017 }
src/wix/test/WixToolsetTest.CoreIntegration/TestData/EnsureTable/StandardActions.wxs new
+7
@@ -0,0 +1,7 @@
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
3 + <Package Name="EnsureTable_StandardActions" Manufacturer="WiX Toolset Worldwide" Version="1.0" UpgradeCode="{EB227D6E-1559-47E4-BE0A-B5E921D68B9C}">
4 + <EnsureTable Id="CCPSearch" />
5 + <EnsureTable Id="RemoveFile" />
6 + </Package>
7 +</Wix>