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>