diff options
| author | Rob Mensching <rob@firegiant.com> | 2020-05-23 01:57:15 -0700 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2020-05-23 02:00:44 -0700 |
| commit | c4497aa78b2d85b2613af64311bf282756aff43a (patch) | |
| tree | 152fd4c2402b195b9370de94d24022b137aa2415 | |
| parent | f08e7529967fa9870faeee6dfa00f326c65cef1e (diff) | |
| download | wix-c4497aa78b2d85b2613af64311bf282756aff43a.tar.gz wix-c4497aa78b2d85b2613af64311bf282756aff43a.tar.bz2 wix-c4497aa78b2d85b2613af64311bf282756aff43a.zip | |
Support instance transforms
3 files changed, 297 insertions, 243 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs index e09c12da..8e901d30 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs | |||
| @@ -373,9 +373,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 373 | } | 373 | } |
| 374 | else // we can create instance transforms since Component Guids are set. | 374 | else // we can create instance transforms since Component Guids are set. |
| 375 | { | 375 | { |
| 376 | #if TODO_FIX_INSTANCE_TRANSFORM | 376 | var command = new CreateInstanceTransformsCommand(section, output, tableDefinitions, this.BackendHelper); |
| 377 | this.CreateInstanceTransforms(this.Output); | 377 | command.Execute(); |
| 378 | #endif | ||
| 379 | } | 378 | } |
| 380 | 379 | ||
| 381 | #if TODO_FINISH_UPDATE | 380 | #if TODO_FINISH_UPDATE |
| @@ -640,244 +639,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
| 640 | } | 639 | } |
| 641 | #endif | 640 | #endif |
| 642 | 641 | ||
| 643 | |||
| 644 | #if TODO_FIX_INSTANCE_TRANSFORM | ||
| 645 | /// <summary> | ||
| 646 | /// Creates instance transform substorages in the output. | ||
| 647 | /// </summary> | ||
| 648 | /// <param name="output">Output containing instance transform definitions.</param> | ||
| 649 | private void CreateInstanceTransforms(Output output) | ||
| 650 | { | ||
| 651 | // Create and add substorages for instance transforms. | ||
| 652 | Table wixInstanceTransformsTable = output.Tables["WixInstanceTransforms"]; | ||
| 653 | if (null != wixInstanceTransformsTable && 0 <= wixInstanceTransformsTable.Rows.Count) | ||
| 654 | { | ||
| 655 | string targetProductCode = null; | ||
| 656 | string targetUpgradeCode = null; | ||
| 657 | string targetProductVersion = null; | ||
| 658 | |||
| 659 | Table targetSummaryInformationTable = output.Tables["_SummaryInformation"]; | ||
| 660 | Table targetPropertyTable = output.Tables["Property"]; | ||
| 661 | |||
| 662 | // Get the data from target database | ||
| 663 | foreach (Row propertyRow in targetPropertyTable.Rows) | ||
| 664 | { | ||
| 665 | if ("ProductCode" == (string)propertyRow[0]) | ||
| 666 | { | ||
| 667 | targetProductCode = (string)propertyRow[1]; | ||
| 668 | } | ||
| 669 | else if ("ProductVersion" == (string)propertyRow[0]) | ||
| 670 | { | ||
| 671 | targetProductVersion = (string)propertyRow[1]; | ||
| 672 | } | ||
| 673 | else if ("UpgradeCode" == (string)propertyRow[0]) | ||
| 674 | { | ||
| 675 | targetUpgradeCode = (string)propertyRow[1]; | ||
| 676 | } | ||
| 677 | } | ||
| 678 | |||
| 679 | // Index the Instance Component Rows. | ||
| 680 | Dictionary<string, ComponentRow> instanceComponentGuids = new Dictionary<string, ComponentRow>(); | ||
| 681 | Table targetInstanceComponentTable = output.Tables["WixInstanceComponent"]; | ||
| 682 | if (null != targetInstanceComponentTable && 0 < targetInstanceComponentTable.Rows.Count) | ||
| 683 | { | ||
| 684 | foreach (Row row in targetInstanceComponentTable.Rows) | ||
| 685 | { | ||
| 686 | // Build up all the instances, we'll get the Components rows from the real Component table. | ||
| 687 | instanceComponentGuids.Add((string)row[0], null); | ||
| 688 | } | ||
| 689 | |||
| 690 | Table targetComponentTable = output.Tables["Component"]; | ||
| 691 | foreach (ComponentRow componentRow in targetComponentTable.Rows) | ||
| 692 | { | ||
| 693 | string component = (string)componentRow[0]; | ||
| 694 | if (instanceComponentGuids.ContainsKey(component)) | ||
| 695 | { | ||
| 696 | instanceComponentGuids[component] = componentRow; | ||
| 697 | } | ||
| 698 | } | ||
| 699 | } | ||
| 700 | |||
| 701 | // Generate the instance transforms | ||
| 702 | foreach (Row instanceRow in wixInstanceTransformsTable.Rows) | ||
| 703 | { | ||
| 704 | string instanceId = (string)instanceRow[0]; | ||
| 705 | |||
| 706 | Output instanceTransform = new Output(instanceRow.SourceLineNumbers); | ||
| 707 | instanceTransform.Type = OutputType.Transform; | ||
| 708 | instanceTransform.Codepage = output.Codepage; | ||
| 709 | |||
| 710 | Table instanceSummaryInformationTable = instanceTransform.EnsureTable(this.TableDefinitions["_SummaryInformation"]); | ||
| 711 | string targetPlatformAndLanguage = null; | ||
| 712 | |||
| 713 | foreach (Row summaryInformationRow in targetSummaryInformationTable.Rows) | ||
| 714 | { | ||
| 715 | if (7 == (int)summaryInformationRow[0]) // PID_TEMPLATE | ||
| 716 | { | ||
| 717 | targetPlatformAndLanguage = (string)summaryInformationRow[1]; | ||
| 718 | } | ||
| 719 | |||
| 720 | // Copy the row's data to the transform. | ||
| 721 | Row copyOfSummaryRow = instanceSummaryInformationTable.CreateRow(null); | ||
| 722 | copyOfSummaryRow[0] = summaryInformationRow[0]; | ||
| 723 | copyOfSummaryRow[1] = summaryInformationRow[1]; | ||
| 724 | } | ||
| 725 | |||
| 726 | // Modify the appropriate properties. | ||
| 727 | Table propertyTable = instanceTransform.EnsureTable(this.TableDefinitions["Property"]); | ||
| 728 | |||
| 729 | // Change the ProductCode property | ||
| 730 | string productCode = (string)instanceRow[2]; | ||
| 731 | if ("*" == productCode) | ||
| 732 | { | ||
| 733 | productCode = Common.GenerateGuid(); | ||
| 734 | } | ||
| 735 | |||
| 736 | Row productCodeRow = propertyTable.CreateRow(instanceRow.SourceLineNumbers); | ||
| 737 | productCodeRow.Operation = RowOperation.Modify; | ||
| 738 | productCodeRow.Fields[1].Modified = true; | ||
| 739 | productCodeRow[0] = "ProductCode"; | ||
| 740 | productCodeRow[1] = productCode; | ||
| 741 | |||
| 742 | // Change the instance property | ||
| 743 | Row instanceIdRow = propertyTable.CreateRow(instanceRow.SourceLineNumbers); | ||
| 744 | instanceIdRow.Operation = RowOperation.Modify; | ||
| 745 | instanceIdRow.Fields[1].Modified = true; | ||
| 746 | instanceIdRow[0] = (string)instanceRow[1]; | ||
| 747 | instanceIdRow[1] = instanceId; | ||
| 748 | |||
| 749 | if (null != instanceRow[3]) | ||
| 750 | { | ||
| 751 | // Change the ProductName property | ||
| 752 | Row productNameRow = propertyTable.CreateRow(instanceRow.SourceLineNumbers); | ||
| 753 | productNameRow.Operation = RowOperation.Modify; | ||
| 754 | productNameRow.Fields[1].Modified = true; | ||
| 755 | productNameRow[0] = "ProductName"; | ||
| 756 | productNameRow[1] = (string)instanceRow[3]; | ||
| 757 | } | ||
| 758 | |||
| 759 | if (null != instanceRow[4]) | ||
| 760 | { | ||
| 761 | // Change the UpgradeCode property | ||
| 762 | Row upgradeCodeRow = propertyTable.CreateRow(instanceRow.SourceLineNumbers); | ||
| 763 | upgradeCodeRow.Operation = RowOperation.Modify; | ||
| 764 | upgradeCodeRow.Fields[1].Modified = true; | ||
| 765 | upgradeCodeRow[0] = "UpgradeCode"; | ||
| 766 | upgradeCodeRow[1] = instanceRow[4]; | ||
| 767 | |||
| 768 | // Change the Upgrade table | ||
| 769 | Table targetUpgradeTable = output.Tables["Upgrade"]; | ||
| 770 | if (null != targetUpgradeTable && 0 <= targetUpgradeTable.Rows.Count) | ||
| 771 | { | ||
| 772 | string upgradeId = (string)instanceRow[4]; | ||
| 773 | Table upgradeTable = instanceTransform.EnsureTable(this.TableDefinitions["Upgrade"]); | ||
| 774 | foreach (Row row in targetUpgradeTable.Rows) | ||
| 775 | { | ||
| 776 | // In case they are upgrading other codes to this new product, leave the ones that don't match the | ||
| 777 | // Product.UpgradeCode intact. | ||
| 778 | if (targetUpgradeCode == (string)row[0]) | ||
| 779 | { | ||
| 780 | Row upgradeRow = upgradeTable.CreateRow(null); | ||
| 781 | upgradeRow.Operation = RowOperation.Add; | ||
| 782 | upgradeRow.Fields[0].Modified = true; | ||
| 783 | // I was hoping to be able to RowOperation.Modify, but that didn't appear to function. | ||
| 784 | // upgradeRow.Fields[0].PreviousData = (string)row[0]; | ||
| 785 | |||
| 786 | // Inserting a new Upgrade record with the updated UpgradeCode | ||
| 787 | upgradeRow[0] = upgradeId; | ||
| 788 | upgradeRow[1] = row[1]; | ||
| 789 | upgradeRow[2] = row[2]; | ||
| 790 | upgradeRow[3] = row[3]; | ||
| 791 | upgradeRow[4] = row[4]; | ||
| 792 | upgradeRow[5] = row[5]; | ||
| 793 | upgradeRow[6] = row[6]; | ||
| 794 | |||
| 795 | // Delete the old row | ||
| 796 | Row upgradeRemoveRow = upgradeTable.CreateRow(null); | ||
| 797 | upgradeRemoveRow.Operation = RowOperation.Delete; | ||
| 798 | upgradeRemoveRow[0] = row[0]; | ||
| 799 | upgradeRemoveRow[1] = row[1]; | ||
| 800 | upgradeRemoveRow[2] = row[2]; | ||
| 801 | upgradeRemoveRow[3] = row[3]; | ||
| 802 | upgradeRemoveRow[4] = row[4]; | ||
| 803 | upgradeRemoveRow[5] = row[5]; | ||
| 804 | upgradeRemoveRow[6] = row[6]; | ||
| 805 | } | ||
| 806 | } | ||
| 807 | } | ||
| 808 | } | ||
| 809 | |||
| 810 | // If there are instance Components generate new GUIDs for them. | ||
| 811 | if (0 < instanceComponentGuids.Count) | ||
| 812 | { | ||
| 813 | Table componentTable = instanceTransform.EnsureTable(this.TableDefinitions["Component"]); | ||
| 814 | foreach (ComponentRow targetComponentRow in instanceComponentGuids.Values) | ||
| 815 | { | ||
| 816 | string guid = targetComponentRow.Guid; | ||
| 817 | if (!String.IsNullOrEmpty(guid)) | ||
| 818 | { | ||
| 819 | Row instanceComponentRow = componentTable.CreateRow(targetComponentRow.SourceLineNumbers); | ||
| 820 | instanceComponentRow.Operation = RowOperation.Modify; | ||
| 821 | instanceComponentRow.Fields[1].Modified = true; | ||
| 822 | instanceComponentRow[0] = targetComponentRow[0]; | ||
| 823 | instanceComponentRow[1] = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, String.Concat(guid, instanceId)).ToString("B").ToUpper(CultureInfo.InvariantCulture); | ||
| 824 | instanceComponentRow[2] = targetComponentRow[2]; | ||
| 825 | instanceComponentRow[3] = targetComponentRow[3]; | ||
| 826 | instanceComponentRow[4] = targetComponentRow[4]; | ||
| 827 | instanceComponentRow[5] = targetComponentRow[5]; | ||
| 828 | } | ||
| 829 | } | ||
| 830 | } | ||
| 831 | |||
| 832 | // Update the summary information | ||
| 833 | Hashtable summaryRows = new Hashtable(instanceSummaryInformationTable.Rows.Count); | ||
| 834 | foreach (Row row in instanceSummaryInformationTable.Rows) | ||
| 835 | { | ||
| 836 | summaryRows[row[0]] = row; | ||
| 837 | |||
| 838 | if ((int)SummaryInformation.Transform.UpdatedPlatformAndLanguage == (int)row[0]) | ||
| 839 | { | ||
| 840 | row[1] = targetPlatformAndLanguage; | ||
| 841 | } | ||
| 842 | else if ((int)SummaryInformation.Transform.ProductCodes == (int)row[0]) | ||
| 843 | { | ||
| 844 | row[1] = String.Concat(targetProductCode, targetProductVersion, ';', productCode, targetProductVersion, ';', targetUpgradeCode); | ||
| 845 | } | ||
| 846 | else if ((int)SummaryInformation.Transform.ValidationFlags == (int)row[0]) | ||
| 847 | { | ||
| 848 | row[1] = 0; | ||
| 849 | } | ||
| 850 | else if ((int)SummaryInformation.Transform.Security == (int)row[0]) | ||
| 851 | { | ||
| 852 | row[1] = "4"; | ||
| 853 | } | ||
| 854 | } | ||
| 855 | |||
| 856 | if (!summaryRows.Contains((int)SummaryInformation.Transform.UpdatedPlatformAndLanguage)) | ||
| 857 | { | ||
| 858 | Row summaryRow = instanceSummaryInformationTable.CreateRow(null); | ||
| 859 | summaryRow[0] = (int)SummaryInformation.Transform.UpdatedPlatformAndLanguage; | ||
| 860 | summaryRow[1] = targetPlatformAndLanguage; | ||
| 861 | } | ||
| 862 | else if (!summaryRows.Contains((int)SummaryInformation.Transform.ValidationFlags)) | ||
| 863 | { | ||
| 864 | Row summaryRow = instanceSummaryInformationTable.CreateRow(null); | ||
| 865 | summaryRow[0] = (int)SummaryInformation.Transform.ValidationFlags; | ||
| 866 | summaryRow[1] = "0"; | ||
| 867 | } | ||
| 868 | else if (!summaryRows.Contains((int)SummaryInformation.Transform.Security)) | ||
| 869 | { | ||
| 870 | Row summaryRow = instanceSummaryInformationTable.CreateRow(null); | ||
| 871 | summaryRow[0] = (int)SummaryInformation.Transform.Security; | ||
| 872 | summaryRow[1] = "4"; | ||
| 873 | } | ||
| 874 | |||
| 875 | output.SubStorages.Add(new SubStorage(instanceId, instanceTransform)); | ||
| 876 | } | ||
| 877 | } | ||
| 878 | } | ||
| 879 | #endif | ||
| 880 | |||
| 881 | /// <summary> | 642 | /// <summary> |
| 882 | /// Validate that there are no duplicate GUIDs in the output. | 643 | /// Validate that there are no duplicate GUIDs in the output. |
| 883 | /// </summary> | 644 | /// </summary> |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateInstanceTransformsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateInstanceTransformsCommand.cs new file mode 100644 index 00000000..772100ca --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateInstanceTransformsCommand.cs | |||
| @@ -0,0 +1,260 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Core.WindowsInstaller.Bind | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Collections.Generic; | ||
| 7 | using System.Linq; | ||
| 8 | using WixToolset.Core.WindowsInstaller.Msi; | ||
| 9 | using WixToolset.Data; | ||
| 10 | using WixToolset.Data.Tuples; | ||
| 11 | using WixToolset.Data.WindowsInstaller; | ||
| 12 | using WixToolset.Data.WindowsInstaller.Rows; | ||
| 13 | using WixToolset.Extensibility.Services; | ||
| 14 | |||
| 15 | internal class CreateInstanceTransformsCommand | ||
| 16 | { | ||
| 17 | public CreateInstanceTransformsCommand(IntermediateSection section, WindowsInstallerData output, TableDefinitionCollection tableDefinitions, IBackendHelper backendHelper) | ||
| 18 | { | ||
| 19 | this.Section = section; | ||
| 20 | this.Output = output; | ||
| 21 | this.TableDefinitions = tableDefinitions; | ||
| 22 | this.BackendHelper = backendHelper; | ||
| 23 | } | ||
| 24 | |||
| 25 | private IntermediateSection Section { get; } | ||
| 26 | |||
| 27 | private WindowsInstallerData Output { get; } | ||
| 28 | |||
| 29 | public TableDefinitionCollection TableDefinitions { get; } | ||
| 30 | |||
| 31 | private IBackendHelper BackendHelper { get; } | ||
| 32 | |||
| 33 | public void Execute() | ||
| 34 | { | ||
| 35 | // Create and add substorages for instance transforms. | ||
| 36 | var wixInstanceTransformsTuples = this.Section.Tuples.OfType<WixInstanceTransformsTuple>(); | ||
| 37 | |||
| 38 | if (wixInstanceTransformsTuples.Any()) | ||
| 39 | { | ||
| 40 | string targetProductCode = null; | ||
| 41 | string targetUpgradeCode = null; | ||
| 42 | string targetProductVersion = null; | ||
| 43 | |||
| 44 | var targetSummaryInformationTable = this.Output.Tables["_SummaryInformation"]; | ||
| 45 | var targetPropertyTable = this.Output.Tables["Property"]; | ||
| 46 | |||
| 47 | // Get the data from target database | ||
| 48 | foreach (var propertyRow in targetPropertyTable.Rows) | ||
| 49 | { | ||
| 50 | if ("ProductCode" == (string)propertyRow[0]) | ||
| 51 | { | ||
| 52 | targetProductCode = (string)propertyRow[1]; | ||
| 53 | } | ||
| 54 | else if ("ProductVersion" == (string)propertyRow[0]) | ||
| 55 | { | ||
| 56 | targetProductVersion = (string)propertyRow[1]; | ||
| 57 | } | ||
| 58 | else if ("UpgradeCode" == (string)propertyRow[0]) | ||
| 59 | { | ||
| 60 | targetUpgradeCode = (string)propertyRow[1]; | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | // Index the Instance Component Rows, we'll get the Components rows from the real Component table. | ||
| 65 | var targetInstanceComponentTable = this.Section.Tuples.OfType<WixInstanceComponentTuple>(); | ||
| 66 | var instanceComponentGuids = targetInstanceComponentTable.ToDictionary(t => t.Id.Id, t => (ComponentRow)null); | ||
| 67 | |||
| 68 | if (instanceComponentGuids.Any()) | ||
| 69 | { | ||
| 70 | var targetComponentTable = this.Output.Tables["Component"]; | ||
| 71 | foreach (ComponentRow componentRow in targetComponentTable.Rows) | ||
| 72 | { | ||
| 73 | var component = (string)componentRow[0]; | ||
| 74 | if (instanceComponentGuids.ContainsKey(component)) | ||
| 75 | { | ||
| 76 | instanceComponentGuids[component] = componentRow; | ||
| 77 | } | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | // Generate the instance transforms | ||
| 82 | foreach (var instanceTuple in wixInstanceTransformsTuples) | ||
| 83 | { | ||
| 84 | var instanceId = instanceTuple.Id.Id; | ||
| 85 | |||
| 86 | var instanceTransform = new WindowsInstallerData(instanceTuple.SourceLineNumbers); | ||
| 87 | instanceTransform.Type = OutputType.Transform; | ||
| 88 | instanceTransform.Codepage = this.Output.Codepage; | ||
| 89 | |||
| 90 | var instanceSummaryInformationTable = instanceTransform.EnsureTable(this.TableDefinitions["_SummaryInformation"]); | ||
| 91 | string targetPlatformAndLanguage = null; | ||
| 92 | |||
| 93 | foreach (var summaryInformationRow in targetSummaryInformationTable.Rows) | ||
| 94 | { | ||
| 95 | if (7 == (int)summaryInformationRow[0]) // PID_TEMPLATE | ||
| 96 | { | ||
| 97 | targetPlatformAndLanguage = (string)summaryInformationRow[1]; | ||
| 98 | } | ||
| 99 | |||
| 100 | // Copy the row's data to the transform. | ||
| 101 | var copyOfSummaryRow = instanceSummaryInformationTable.CreateRow(summaryInformationRow.SourceLineNumbers); | ||
| 102 | copyOfSummaryRow[0] = summaryInformationRow[0]; | ||
| 103 | copyOfSummaryRow[1] = summaryInformationRow[1]; | ||
| 104 | } | ||
| 105 | |||
| 106 | // Modify the appropriate properties. | ||
| 107 | var propertyTable = instanceTransform.EnsureTable(this.TableDefinitions["Property"]); | ||
| 108 | |||
| 109 | // Change the ProductCode property | ||
| 110 | var productCode = instanceTuple.ProductCode; | ||
| 111 | if ("*" == productCode) | ||
| 112 | { | ||
| 113 | productCode = Common.GenerateGuid(); | ||
| 114 | } | ||
| 115 | |||
| 116 | var productCodeRow = propertyTable.CreateRow(instanceTuple.SourceLineNumbers); | ||
| 117 | productCodeRow.Operation = RowOperation.Modify; | ||
| 118 | productCodeRow.Fields[1].Modified = true; | ||
| 119 | productCodeRow[0] = "ProductCode"; | ||
| 120 | productCodeRow[1] = productCode; | ||
| 121 | |||
| 122 | // Change the instance property | ||
| 123 | var instanceIdRow = propertyTable.CreateRow(instanceTuple.SourceLineNumbers); | ||
| 124 | instanceIdRow.Operation = RowOperation.Modify; | ||
| 125 | instanceIdRow.Fields[1].Modified = true; | ||
| 126 | instanceIdRow[0] = instanceTuple.PropertyId; | ||
| 127 | instanceIdRow[1] = instanceId; | ||
| 128 | |||
| 129 | if (!String.IsNullOrEmpty(instanceTuple.ProductName)) | ||
| 130 | { | ||
| 131 | // Change the ProductName property | ||
| 132 | var productNameRow = propertyTable.CreateRow(instanceTuple.SourceLineNumbers); | ||
| 133 | productNameRow.Operation = RowOperation.Modify; | ||
| 134 | productNameRow.Fields[1].Modified = true; | ||
| 135 | productNameRow[0] = "ProductName"; | ||
| 136 | productNameRow[1] = instanceTuple.ProductName; | ||
| 137 | } | ||
| 138 | |||
| 139 | if (!String.IsNullOrEmpty(instanceTuple.UpgradeCode)) | ||
| 140 | { | ||
| 141 | // Change the UpgradeCode property | ||
| 142 | var upgradeCodeRow = propertyTable.CreateRow(instanceTuple.SourceLineNumbers); | ||
| 143 | upgradeCodeRow.Operation = RowOperation.Modify; | ||
| 144 | upgradeCodeRow.Fields[1].Modified = true; | ||
| 145 | upgradeCodeRow[0] = "UpgradeCode"; | ||
| 146 | upgradeCodeRow[1] = instanceTuple.UpgradeCode; | ||
| 147 | |||
| 148 | // Change the Upgrade table | ||
| 149 | var targetUpgradeTable = this.Output.Tables["Upgrade"]; | ||
| 150 | if (null != targetUpgradeTable && 0 <= targetUpgradeTable.Rows.Count) | ||
| 151 | { | ||
| 152 | var upgradeId = instanceTuple.UpgradeCode; | ||
| 153 | var upgradeTable = instanceTransform.EnsureTable(this.TableDefinitions["Upgrade"]); | ||
| 154 | foreach (var row in targetUpgradeTable.Rows) | ||
| 155 | { | ||
| 156 | // In case they are upgrading other codes to this new product, leave the ones that don't match the | ||
| 157 | // Product.UpgradeCode intact. | ||
| 158 | if (targetUpgradeCode == (string)row[0]) | ||
| 159 | { | ||
| 160 | var upgradeRow = upgradeTable.CreateRow(row.SourceLineNumbers); | ||
| 161 | upgradeRow.Operation = RowOperation.Add; | ||
| 162 | upgradeRow.Fields[0].Modified = true; | ||
| 163 | // I was hoping to be able to RowOperation.Modify, but that didn't appear to function. | ||
| 164 | // upgradeRow.Fields[0].PreviousData = (string)row[0]; | ||
| 165 | |||
| 166 | // Inserting a new Upgrade record with the updated UpgradeCode | ||
| 167 | upgradeRow[0] = upgradeId; | ||
| 168 | upgradeRow[1] = row[1]; | ||
| 169 | upgradeRow[2] = row[2]; | ||
| 170 | upgradeRow[3] = row[3]; | ||
| 171 | upgradeRow[4] = row[4]; | ||
| 172 | upgradeRow[5] = row[5]; | ||
| 173 | upgradeRow[6] = row[6]; | ||
| 174 | |||
| 175 | // Delete the old row | ||
| 176 | var upgradeRemoveRow = upgradeTable.CreateRow(row.SourceLineNumbers); | ||
| 177 | upgradeRemoveRow.Operation = RowOperation.Delete; | ||
| 178 | upgradeRemoveRow[0] = row[0]; | ||
| 179 | upgradeRemoveRow[1] = row[1]; | ||
| 180 | upgradeRemoveRow[2] = row[2]; | ||
| 181 | upgradeRemoveRow[3] = row[3]; | ||
| 182 | upgradeRemoveRow[4] = row[4]; | ||
| 183 | upgradeRemoveRow[5] = row[5]; | ||
| 184 | upgradeRemoveRow[6] = row[6]; | ||
| 185 | } | ||
| 186 | } | ||
| 187 | } | ||
| 188 | } | ||
| 189 | |||
| 190 | // If there are instance Components generate new GUIDs for them. | ||
| 191 | if (0 < instanceComponentGuids.Count) | ||
| 192 | { | ||
| 193 | var componentTable = instanceTransform.EnsureTable(this.TableDefinitions["Component"]); | ||
| 194 | foreach (var targetComponentRow in instanceComponentGuids.Values) | ||
| 195 | { | ||
| 196 | var guid = targetComponentRow.Guid; | ||
| 197 | if (!String.IsNullOrEmpty(guid)) | ||
| 198 | { | ||
| 199 | var instanceComponentRow = componentTable.CreateRow(targetComponentRow.SourceLineNumbers); | ||
| 200 | instanceComponentRow.Operation = RowOperation.Modify; | ||
| 201 | instanceComponentRow.Fields[1].Modified = true; | ||
| 202 | instanceComponentRow[0] = targetComponentRow[0]; | ||
| 203 | instanceComponentRow[1] = this.BackendHelper.CreateGuid(BindDatabaseCommand.WixComponentGuidNamespace, String.Concat(guid, instanceId)); | ||
| 204 | instanceComponentRow[2] = targetComponentRow[2]; | ||
| 205 | instanceComponentRow[3] = targetComponentRow[3]; | ||
| 206 | instanceComponentRow[4] = targetComponentRow[4]; | ||
| 207 | instanceComponentRow[5] = targetComponentRow[5]; | ||
| 208 | } | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | // Update the summary information | ||
| 213 | var summaryRows = new Dictionary<int, Row>(instanceSummaryInformationTable.Rows.Count); | ||
| 214 | foreach (var row in instanceSummaryInformationTable.Rows) | ||
| 215 | { | ||
| 216 | summaryRows[(int)row[0]] = row; | ||
| 217 | |||
| 218 | if ((int)SummaryInformation.Transform.UpdatedPlatformAndLanguage == (int)row[0]) | ||
| 219 | { | ||
| 220 | row[1] = targetPlatformAndLanguage; | ||
| 221 | } | ||
| 222 | else if ((int)SummaryInformation.Transform.ProductCodes == (int)row[0]) | ||
| 223 | { | ||
| 224 | row[1] = String.Concat(targetProductCode, targetProductVersion, ';', productCode, targetProductVersion, ';', targetUpgradeCode); | ||
| 225 | } | ||
| 226 | else if ((int)SummaryInformation.Transform.ValidationFlags == (int)row[0]) | ||
| 227 | { | ||
| 228 | row[1] = 0; | ||
| 229 | } | ||
| 230 | else if ((int)SummaryInformation.Transform.Security == (int)row[0]) | ||
| 231 | { | ||
| 232 | row[1] = "4"; | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | if (!summaryRows.ContainsKey((int)SummaryInformation.Transform.UpdatedPlatformAndLanguage)) | ||
| 237 | { | ||
| 238 | var summaryRow = instanceSummaryInformationTable.CreateRow(instanceTuple.SourceLineNumbers); | ||
| 239 | summaryRow[0] = (int)SummaryInformation.Transform.UpdatedPlatformAndLanguage; | ||
| 240 | summaryRow[1] = targetPlatformAndLanguage; | ||
| 241 | } | ||
| 242 | else if (!summaryRows.ContainsKey((int)SummaryInformation.Transform.ValidationFlags)) | ||
| 243 | { | ||
| 244 | var summaryRow = instanceSummaryInformationTable.CreateRow(instanceTuple.SourceLineNumbers); | ||
| 245 | summaryRow[0] = (int)SummaryInformation.Transform.ValidationFlags; | ||
| 246 | summaryRow[1] = "0"; | ||
| 247 | } | ||
| 248 | else if (!summaryRows.ContainsKey((int)SummaryInformation.Transform.Security)) | ||
| 249 | { | ||
| 250 | var summaryRow = instanceSummaryInformationTable.CreateRow(instanceTuple.SourceLineNumbers); | ||
| 251 | summaryRow[0] = (int)SummaryInformation.Transform.Security; | ||
| 252 | summaryRow[1] = "4"; | ||
| 253 | } | ||
| 254 | |||
| 255 | this.Output.SubStorages.Add(new SubStorage(instanceId, instanceTransform)); | ||
| 256 | } | ||
| 257 | } | ||
| 258 | } | ||
| 259 | } | ||
| 260 | } | ||
diff --git a/src/test/WixToolsetTest.CoreIntegration/MsiFixture.cs b/src/test/WixToolsetTest.CoreIntegration/MsiFixture.cs index 075f7733..69258ae4 100644 --- a/src/test/WixToolsetTest.CoreIntegration/MsiFixture.cs +++ b/src/test/WixToolsetTest.CoreIntegration/MsiFixture.cs | |||
| @@ -790,7 +790,7 @@ namespace WixToolsetTest.CoreIntegration | |||
| 790 | } | 790 | } |
| 791 | } | 791 | } |
| 792 | 792 | ||
| 793 | [Fact(Skip = "Not implemented yet.")] | 793 | [Fact] |
| 794 | public void CanBuildInstanceTransform() | 794 | public void CanBuildInstanceTransform() |
| 795 | { | 795 | { |
| 796 | var folder = TestData.Get(@"TestData\InstanceTransform"); | 796 | var folder = TestData.Get(@"TestData\InstanceTransform"); |
| @@ -813,7 +813,30 @@ namespace WixToolsetTest.CoreIntegration | |||
| 813 | result.AssertSuccess(); | 813 | result.AssertSuccess(); |
| 814 | 814 | ||
| 815 | var output = WindowsInstallerData.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb"), false); | 815 | var output = WindowsInstallerData.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb"), false); |
| 816 | Assert.NotEmpty(output.SubStorages); | 816 | var substorage = output.SubStorages.Single(); |
| 817 | Assert.Equal("I1", substorage.Name); | ||
| 818 | |||
| 819 | var data = substorage.Data; | ||
| 820 | Assert.Equal(new[] | ||
| 821 | { | ||
| 822 | "_SummaryInformation", | ||
| 823 | "Property", | ||
| 824 | "Upgrade" | ||
| 825 | }, data.Tables.Select(t => t.Name).ToArray()); | ||
| 826 | |||
| 827 | Assert.Equal(new[] | ||
| 828 | { | ||
| 829 | "INSTANCEPROPERTY\tI1", | ||
| 830 | "ProductName\tMsiPackage (Instance 1)", | ||
| 831 | }, JoinRows(data.Tables["Property"])); | ||
| 832 | |||
| 833 | Assert.Equal(new[] | ||
| 834 | { | ||
| 835 | "{047730A5-30FE-4A62-A520-DA9381B8226A}\t\t1.0.0.0\t1033\t1\t\tWIX_UPGRADE_DETECTED", | ||
| 836 | "{047730A5-30FE-4A62-A520-DA9381B8226A}\t\t1.0.0.0\t1033\t1\t0\t0", | ||
| 837 | "{047730A5-30FE-4A62-A520-DA9381B8226A}\t1.0.0.0\t\t1033\t2\t\tWIX_DOWNGRADE_DETECTED", | ||
| 838 | "{047730A5-30FE-4A62-A520-DA9381B8226A}\t1.0.0.0\t\t1033\t2\t0\t0" | ||
| 839 | }, JoinRows(data.Tables["Upgrade"])); | ||
| 817 | } | 840 | } |
| 818 | } | 841 | } |
| 819 | 842 | ||
| @@ -850,5 +873,15 @@ namespace WixToolsetTest.CoreIntegration | |||
| 850 | Assert.False(File.Exists(msiPath)); | 873 | Assert.False(File.Exists(msiPath)); |
| 851 | } | 874 | } |
| 852 | } | 875 | } |
| 876 | |||
| 877 | private static string[] JoinRows(Table table) | ||
| 878 | { | ||
| 879 | return table.Rows.Select(r => JoinFields(r.Fields)).ToArray(); | ||
| 880 | |||
| 881 | string JoinFields(Field[] fields) | ||
| 882 | { | ||
| 883 | return String.Join('\t', fields.Select(f => f.ToString())); | ||
| 884 | } | ||
| 885 | } | ||
| 853 | } | 886 | } |
| 854 | } | 887 | } |
