| 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 WixTestTools |
| 4 | { |
| 5 | using System; |
| 6 | using System.IO; |
| 7 | using System.Linq; |
| 8 | using WixToolset.Data; |
| 9 | using WixToolset.Data.Symbols; |
| 10 | using WixToolset.Data.WindowsInstaller; |
| 11 | using static WixTestTools.MSIExec; |
| 12 | |
| 13 | public partial class PackageInstaller : IDisposable |
| 14 | { |
| 15 | public PackageInstaller(WixTestContext testContext, string filename) |
| 16 | { |
| 17 | this.Package = Path.Combine(testContext.TestDataFolder, $"{filename}.msi"); |
| 18 | this.PackagePdb = Path.Combine(testContext.TestDataFolder, $"{filename}.wixpdb"); |
| 19 | this.TestContext = testContext; |
| 20 | |
| 21 | using var wixOutput = WixOutput.Read(this.PackagePdb); |
| 22 | |
| 23 | var intermediate = Intermediate.Load(wixOutput); |
| 24 | var section = intermediate.Sections.Single(); |
| 25 | var platformSummary = section.Symbols.OfType<SummaryInformationSymbol>().Single(s => s.PropertyId == SummaryInformationType.PlatformAndLanguage); |
| 26 | var platformString = platformSummary.Value.Split(new char[] { ';' }, 2)[0]; |
| 27 | this.IsX64 = platformString != "Intel"; |
| 28 | |
| 29 | this.WiData = WindowsInstallerData.Load(wixOutput); |
| 30 | } |
| 31 | |
| 32 | public string Package { get; } |
| 33 | |
| 34 | private WixTestContext TestContext { get; } |
| 35 | |
| 36 | public string TestGroupName => this.TestContext.TestGroupName; |
| 37 | |
| 38 | public string TestName => this.TestContext.TestName; |
| 39 | |
| 40 | /// <summary> |
| 41 | /// Installs a .msi file |
| 42 | /// </summary> |
| 43 | /// <param name="expectedExitCode">Expected exit code</param> |
| 44 | /// <param name="otherArguments">Other arguments to pass to MSIExec.</param> |
| 45 | /// <returns>MSIExec log File</returns> |
| 46 | public string InstallProduct(MSIExecReturnCode expectedExitCode = MSIExecReturnCode.SUCCESS, params string[] otherArguments) |
| 47 | { |
| 48 | return this.RunMSIExec(MSIExecMode.Install, otherArguments, expectedExitCode); |
| 49 | } |
| 50 | |
| 51 | /// <summary> |
| 52 | /// Uninstalls a .msi file |
| 53 | /// </summary> |
| 54 | /// <param name="expectedExitCode">Expected exit code</param> |
| 55 | /// <param name="otherArguments">Other arguments to pass to MSIExec.</param> |
| 56 | /// <returns>MSIExec log File</returns> |
| 57 | public string UninstallProduct(MSIExecReturnCode expectedExitCode = MSIExecReturnCode.SUCCESS, params string[] otherArguments) |
| 58 | { |
| 59 | return this.RunMSIExec(MSIExecMode.Uninstall, otherArguments, expectedExitCode); |
| 60 | } |
| 61 | |
| 62 | /// <summary> |
| 63 | /// Repairs a .msi file |
| 64 | /// </summary> |
| 65 | /// <param name="expectedExitCode">Expected exit code</param> |
| 66 | /// <param name="otherArguments">Other arguments to pass to msiexe.exe.</param> |
| 67 | /// <returns>MSIExec log File</returns> |
| 68 | public string RepairProduct(MSIExecReturnCode expectedExitCode = MSIExecReturnCode.SUCCESS, params string[] otherArguments) |
| 69 | { |
| 70 | return this.RunMSIExec(MSIExecMode.Repair, otherArguments, expectedExitCode); |
| 71 | } |
| 72 | |
| 73 | /// <summary> |
| 74 | /// Executes MSIExec on a .msi file |
| 75 | /// </summary> |
| 76 | /// <param name="mode">Mode of execution for MSIExec</param> |
| 77 | /// <param name="otherArguments">Other arguments to pass to MSIExec.</param> |
| 78 | /// <param name="expectedExitCode">Expected exit code</param> |
| 79 | /// <returns>MSIExec exit code</returns> |
| 80 | private string RunMSIExec(MSIExecMode mode, string[] otherArguments, MSIExecReturnCode expectedExitCode, bool assertOnError = true) |
| 81 | { |
| 82 | // Generate the log file name. |
| 83 | var logFile = Path.Combine(Path.GetTempPath(), String.Format("{0}_{1}_{2:yyyyMMddhhmmss}_{4}_{3}.log", this.TestGroupName, this.TestName, DateTime.UtcNow, Path.GetFileNameWithoutExtension(this.Package), mode)); |
| 84 | |
| 85 | var msiexec = new MSIExec |
| 86 | { |
| 87 | Product = this.Package, |
| 88 | ExecutionMode = mode, |
| 89 | OtherArguments = null != otherArguments ? String.Join(" ", otherArguments) : null, |
| 90 | ExpectedExitCode = expectedExitCode, |
| 91 | LogFile = logFile, |
| 92 | }; |
| 93 | |
| 94 | msiexec.Run(assertOnError); |
| 95 | return msiexec.LogFile; |
| 96 | } |
| 97 | |
| 98 | public void Dispose() |
| 99 | { |
| 100 | string[] args = { "IGNOREDEPENDENCIES=ALL", "WIXFAILWHENDEFERRED=0" }; |
| 101 | this.RunMSIExec(MSIExecMode.Cleanup, args, MSIExecReturnCode.SUCCESS, assertOnError: false); |
| 102 | } |
| 103 | } |
| 104 | } |