From fe057678c6c15dd723218b0c82b25ec7e58378b8 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Wed, 28 Dec 2022 18:02:54 -0800 Subject: Fix decompiling UI Fixes 7117 --- .../Decompile/Decompiler.cs | 110 ++-- .../Decompile/Names.cs | 1 + .../DecompileFixture.cs | 24 +- .../TestData/Decompile/ExpectedUI.wxs | 563 +++++++++++++++++++++ .../TestData/Decompile/ui.msi | Bin 0 -> 290816 bytes 5 files changed, 632 insertions(+), 66 deletions(-) create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/Decompile/ExpectedUI.wxs create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/Decompile/ui.msi diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs b/src/wix/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs index c953316d..e2a6750e 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Decompile/Decompiler.cs @@ -256,6 +256,11 @@ namespace WixToolset.Core.WindowsInstaller.Decompile } } + private static XAttribute XAttributeIfNotNull(string attributeName, string value) + { + return value is null ? null : new XAttribute(attributeName, value); + } + private static XAttribute XAttributeIfNotNull(string attributeName, Row row, int column) { return row.IsColumnNull(column) ? null : new XAttribute(attributeName, row.FieldAsString(column)); @@ -352,62 +357,15 @@ namespace WixToolset.Core.WindowsInstaller.Decompile new XAttribute("Action", actionSymbol.Action), String.IsNullOrEmpty(actionSymbol.Condition) ? null : new XAttribute("Condition", actionSymbol.Condition)); - switch (actionSymbol.Sequence) - { - case (-4): - xAction.SetAttributeValue("OnExit", "suspend"); - break; - case (-3): - xAction.SetAttributeValue("OnExit", "error"); - break; - case (-2): - xAction.SetAttributeValue("OnExit", "cancel"); - break; - case (-1): - xAction.SetAttributeValue("OnExit", "success"); - break; - default: - if (null != actionSymbol.Before) - { - xAction.SetAttributeValue("Before", actionSymbol.Before); - } - else if (null != actionSymbol.After) - { - xAction.SetAttributeValue("After", actionSymbol.After); - } - else if (actionSymbol.Sequence.HasValue) - { - xAction.SetAttributeValue("Sequence", actionSymbol.Sequence.Value); - } - break; - } + AssignActionSequence(actionSymbol, xAction); } else if (this.DecompilerHelper.TryGetIndexedElement("Dialog", actionSymbol.Action, out var _)) // dialog { - xAction = new XElement(Names.CustomElement, + xAction = new XElement(Names.ShowElement, new XAttribute("Dialog", actionSymbol.Action), - new XAttribute("Condition", actionSymbol.Condition)); + XAttributeIfNotNull("Condition", actionSymbol.Condition)); - switch (actionSymbol.Sequence) - { - case (-4): - xAction.SetAttributeValue("OnExit", "suspend"); - break; - case (-3): - xAction.SetAttributeValue("OnExit", "error"); - break; - case (-2): - xAction.SetAttributeValue("OnExit", "cancel"); - break; - case (-1): - xAction.SetAttributeValue("OnExit", "success"); - break; - default: - SetAttributeIfNotNull(xAction, "Before", actionSymbol.Before); - SetAttributeIfNotNull(xAction, "After", actionSymbol.After); - SetAttributeIfNotNull(xAction, "Sequence", actionSymbol.Sequence); - break; - } + AssignActionSequence(actionSymbol, xAction); } else // possibly a standard action without suggested sequence information { @@ -868,7 +826,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile // add tabbable controls while (null != xControl) { - var controlId = xControl.Attribute("Id"); + var controlId = xControl.Attribute("Id").Value; var controlRow = controlRows[String.Concat(dialogId, DecompilerConstants.PrimaryKeyDelimiter, controlId)]; xControl.SetAttributeValue("TabSkip", "no"); @@ -913,7 +871,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile } // set cancel control - var controlCancel = dialogRow.FieldAsString(8); + var controlCancel = dialogRow.FieldAsString(9); if (!String.IsNullOrEmpty(controlCancel)) { if (this.DecompilerHelper.TryGetIndexedElement("Control", dialogId, controlCancel, out var xCancelControl)) @@ -3428,7 +3386,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile new XAttribute("Y", controlRow.Y), new XAttribute("Width", controlRow.Width), new XAttribute("Height", controlRow.Height), - new XAttribute("Text", controlRow.Text)); + XAttributeIfNotNull("Text", controlRow.Text)); if (!controlRow.IsColumnNull(7)) { @@ -3699,8 +3657,13 @@ namespace WixToolset.Core.WindowsInstaller.Decompile foreach (var row in table.Rows) { - var xPublish = new XElement(Names.PublishElement, - new XAttribute("Condition", row.FieldAsString(4))); + var xPublish = new XElement(Names.PublishElement); + var condition = row.FieldAsString(4); + + if (!String.IsNullOrEmpty(condition) && condition != "1") + { + xPublish.Add(new XAttribute("Condition", condition)); + } var publishEvent = row.FieldAsString(2); if (publishEvent.StartsWith("[", StringComparison.Ordinal) && publishEvent.EndsWith("]", StringComparison.Ordinal)) @@ -7455,7 +7418,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile { var xUiText = new XElement(Names.UITextElement, new XAttribute("Id", row.FieldAsString(0)), - new XAttribute("Value", row.FieldAsString(1))); + XAttributeIfNotNull("Value", row, 1)); this.UIElement.Add(xUiText); } @@ -7538,6 +7501,39 @@ namespace WixToolset.Core.WindowsInstaller.Decompile } } + private static void AssignActionSequence(WixActionSymbol actionSymbol, XElement xAction) + { + switch (actionSymbol.Sequence) + { + case (-4): + xAction.SetAttributeValue("OnExit", "suspend"); + break; + case (-3): + xAction.SetAttributeValue("OnExit", "error"); + break; + case (-2): + xAction.SetAttributeValue("OnExit", "cancel"); + break; + case (-1): + xAction.SetAttributeValue("OnExit", "success"); + break; + default: + if (null != actionSymbol.Before) + { + xAction.SetAttributeValue("Before", actionSymbol.Before); + } + else if (null != actionSymbol.After) + { + xAction.SetAttributeValue("After", actionSymbol.After); + } + else if (actionSymbol.Sequence.HasValue) + { + xAction.SetAttributeValue("Sequence", actionSymbol.Sequence.Value); + } + break; + } + } + /// /// Checks the InstallExecuteSequence table to determine where RemoveExistingProducts is scheduled and removes it. /// diff --git a/src/wix/WixToolset.Core.WindowsInstaller/Decompile/Names.cs b/src/wix/WixToolset.Core.WindowsInstaller/Decompile/Names.cs index db65bbf7..e49c1df9 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/Decompile/Names.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/Decompile/Names.cs @@ -15,6 +15,7 @@ namespace WixToolset.Core.WindowsInstaller.Decompile public static readonly XName SummaryInformationElement = WxsNamespace + "SummaryInformation"; public static readonly XName CustomElement = WxsNamespace + "Custom"; + public static readonly XName ShowElement = WxsNamespace + "Show"; public static readonly XName AdminExecuteSequenceElement = WxsNamespace + "AdminExecuteSequence"; public static readonly XName AdminUISequenceElement = WxsNamespace + "AdminUISequence"; diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/DecompileFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/DecompileFixture.cs index 77311302..a4915a3a 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/DecompileFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/DecompileFixture.cs @@ -9,7 +9,7 @@ namespace WixToolsetTest.CoreIntegration public class DecompileFixture { - private static void DecompileAndCompare(string sourceFolder, string msiName, string expectedWxsName) + private static void DecompileAndCompare(string msiName, string expectedWxsName, params string[] sourceFolder) { var folder = TestData.Get(sourceFolder); @@ -35,19 +35,19 @@ namespace WixToolsetTest.CoreIntegration [Fact] public void CanDecompileSingleFileCompressed() { - DecompileAndCompare(@"TestData\DecompileSingleFileCompressed", "example.msi", "Expected.wxs"); + DecompileAndCompare("example.msi", "Expected.wxs", "TestData", "DecompileSingleFileCompressed"); } [Fact] public void CanDecompile64BitSingleFileCompressed() { - DecompileAndCompare(@"TestData\DecompileSingleFileCompressed64", "example.msi", "Expected.wxs"); + DecompileAndCompare("example.msi", "Expected.wxs", "TestData", "DecompileSingleFileCompressed64"); } [Fact] public void CanDecompileNestedDirSearchUnderRegSearch() { - DecompileAndCompare(@"TestData\AppSearch", "NestedDirSearchUnderRegSearch.msi", "DecompiledNestedDirSearchUnderRegSearch.wxs"); + DecompileAndCompare("NestedDirSearchUnderRegSearch.msi", "DecompiledNestedDirSearchUnderRegSearch.wxs", "TestData", "AppSearch"); } [Fact] @@ -56,31 +56,37 @@ namespace WixToolsetTest.CoreIntegration // The input MSI was not created using standard methods, it is an example of a real world database that needs to be decompiled. // The Class/@Feature_ column has length of 32, the File/@Attributes has length of 2, // and numerous foreign key relationships are missing. - DecompileAndCompare(@"TestData\Class", "OldClassTableDef.msi", "DecompiledOldClassTableDef.wxs"); + DecompileAndCompare("OldClassTableDef.msi", "DecompiledOldClassTableDef.wxs", "TestData", "Class"); } [Fact] public void CanDecompileSequenceTables() { - DecompileAndCompare(@"TestData\SequenceTables", "SequenceTables.msi", "DecompiledSequenceTables.wxs"); + DecompileAndCompare("SequenceTables.msi", "DecompiledSequenceTables.wxs", "TestData", "SequenceTables"); } [Fact] public void CanDecompileShortcuts() { - DecompileAndCompare(@"TestData\Shortcut", "shortcuts.msi", "DecompiledShortcuts.wxs"); + DecompileAndCompare("shortcuts.msi", "DecompiledShortcuts.wxs", "TestData", "Shortcut"); } [Fact] public void CanDecompileNullComponent() { - DecompileAndCompare(@"TestData\DecompileNullComponent", "example.msi", "Expected.wxs"); + DecompileAndCompare("example.msi", "Expected.wxs", "TestData", "DecompileNullComponent"); } [Fact] public void CanDecompileMergeModuleWithTargetDirComponent() { - DecompileAndCompare(@"TestData\DecompileTargetDirMergeModule", "MergeModule1.msm", "Expected.wxs"); + DecompileAndCompare("MergeModule1.msm", "Expected.wxs", "TestData", "DecompileTargetDirMergeModule"); + } + + [Fact] + public void CanDecompileUI() + { + DecompileAndCompare("ui.msi", "ExpectedUI.wxs", "TestData", "Decompile"); } } } diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Decompile/ExpectedUI.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Decompile/ExpectedUI.wxs new file mode 100644 index 00000000..0526efc1 --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Decompile/ExpectedUI.wxs @@ -0,0 +1,563 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Decompile/ui.msi b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Decompile/ui.msi new file mode 100644 index 00000000..20395fb0 Binary files /dev/null and b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Decompile/ui.msi differ -- cgit v1.2.3-55-g6feb