// 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.
namespace WixTestTools
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
public partial class BundleInstaller : IDisposable
{
public BundleInstaller(WixTestContext testContext, string name)
{
this.Bundle = Path.Combine(testContext.TestDataFolder, $"{name}.exe");
this.BundlePdb = Path.Combine(testContext.TestDataFolder, $"{name}.wixpdb");
this.TestContext = testContext;
this.TestGroupName = testContext.TestGroupName;
this.TestName = testContext.TestName;
}
public string Bundle { get; }
private WixTestContext TestContext { get; }
public string TestGroupName { get; }
public string TestName { get; }
public int? AlternateExitCode { get; set; }
public string LogDirectory { get; set; }
public int? LastExitCode { get; set; }
///
/// Runs the bundle asking for help.
///
/// Expected exit code, defaults to success.
/// Optional arguments to pass to the tool.
/// Path to the generated log file.
public string Help(int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
{
var newArgumentList = new List();
newArgumentList.Add("-help");
newArgumentList.AddRange(arguments);
return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Custom, newArgumentList.ToArray());
}
///
/// Installs the bundle with optional arguments.
///
/// Expected exit code, defaults to success.
/// Optional arguments to pass to the tool.
/// Path to the generated log file.
public string Install(int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
{
return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Install, arguments);
}
///
/// Installs the bundle with optional arguments.
///
/// This should be the bundle in the package cache.
/// Expected exit code, defaults to success.
/// Optional arguments to pass to the tool.
/// Path to the generated log file.
public string Install(string bundlePath, int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
{
return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Install, arguments, bundlePath: bundlePath);
}
///
/// Calls Layout for the bundle with optional arguments.
///
/// The destination directory.
/// Expected exit code, defaults to success.
/// Optional arguments to pass to the tool.
/// Path to the generated log file.
public string Layout(string layoutDirectory, int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
{
return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.AdministrativeInstall, arguments, layoutDirectory: layoutDirectory);
}
///
/// Calls Layout for the bundle with optional arguments.
///
/// Path to the bundle to run.
/// The destination directory.
/// Expected exit code, defaults to success.
/// Optional arguments to pass to the tool.
/// Path to the generated log file.
public string Layout(string bundlePath, string layoutDirectory, int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
{
return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.AdministrativeInstall, arguments, bundlePath: bundlePath, layoutDirectory: layoutDirectory);
}
///
/// Modify the bundle with optional arguments.
///
/// Expected exit code, defaults to success.
/// Optional arguments to pass to the tool.
/// Path to the generated log file.
public string Modify(int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
{
return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Modify, arguments);
}
///
/// Modify the bundle with optional arguments.
///
/// This should be the bundle in the package cache.
/// Expected exit code, defaults to success.
/// Optional arguments to pass to the tool.
/// Path to the generated log file.
public string Modify(string bundlePath, int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
{
return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Modify, arguments, bundlePath: bundlePath);
}
///
/// Repairs the bundle with optional arguments.
///
/// Expected exit code, defaults to success.
/// Optional arguments to pass to the tool.
/// Path to the generated log file.
public string Repair(int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
{
return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Repair, arguments);
}
///
/// Uninstalls the bundle with optional arguments.
///
/// Expected exit code, defaults to success.
/// Optional arguments to pass to the tool.
/// Path to the generated log file.
public string Uninstall(int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
{
return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Uninstall, arguments);
}
///
/// Uninstalls the bundle at the given path with optional arguments.
///
/// This should be the bundle in the package cache.
/// Expected exit code, defaults to success.
/// Optional arguments to pass to the tool.
/// Path to the generated log file.
public string Uninstall(string bundlePath, int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
{
return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Uninstall, arguments, bundlePath: bundlePath);
}
///
/// Uninstalls the bundle unsafely with optional arguments.
///
/// Expected exit code, defaults to success.
/// Optional arguments to pass to the tool.
/// Path to the generated log file.
public string UnsafeUninstall(int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
{
var newArgumentList = new List();
newArgumentList.Add("-unsafeuninstall");
newArgumentList.AddRange(arguments);
return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Custom, newArgumentList.ToArray());
}
///
/// Uninstalls the bundle unsafely at the given path with optional arguments.
///
/// This should be the bundle in the package cache.
/// Expected exit code, defaults to success.
/// Optional arguments to pass to the tool.
/// Path to the generated log file.
public string UnsafeUninstall(string bundlePath, int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
{
var newArgumentList = new List();
newArgumentList.Add("-unsafeuninstall");
newArgumentList.AddRange(arguments);
return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Custom, newArgumentList.ToArray(), bundlePath: bundlePath);
}
///
/// Executes the bundle with optional arguments.
///
/// Expected exit code.
/// Install mode.
/// Optional arguments to pass to the tool.
/// Path to the generated log file.
private string RunBundleWithArguments(int expectedExitCode, MSIExec.MSIExecMode mode, string[] arguments, bool assertOnError = true, string bundlePath = null, string layoutDirectory = null)
{
TestTool bundle = new TestTool(bundlePath ?? this.Bundle);
var sb = new StringBuilder();
// Be sure to run silent.
sb.Append(" -quiet");
// Generate the log file name.
string logFile = Path.Combine(this.LogDirectory ?? Path.GetTempPath(), String.Format("{0}_{1}_{2:yyyyMMddhhmmss}_{4}_{3}.log", this.TestGroupName, this.TestName, DateTime.UtcNow, Path.GetFileNameWithoutExtension(this.Bundle), mode));
sb.AppendFormat(" -log \"{0}\"", logFile);
// Set operation.
switch (mode)
{
case MSIExec.MSIExecMode.AdministrativeInstall:
sb.Append($" -layout \"{layoutDirectory}\"");
break;
case MSIExec.MSIExecMode.Modify:
sb.Append(" -modify");
break;
case MSIExec.MSIExecMode.Repair:
sb.Append(" -repair");
break;
case MSIExec.MSIExecMode.Cleanup:
case MSIExec.MSIExecMode.Uninstall:
sb.Append(" -uninstall");
break;
}
// Add additional arguments.
if (null != arguments)
{
sb.Append(" ");
sb.Append(String.Join(" ", arguments));
}
// Set the arguments.
bundle.Arguments = sb.ToString();
// Run the tool and assert the expected code.
bundle.ExpectedExitCode = expectedExitCode;
bundle.AlternateExitCode = this.AlternateExitCode;
var result = bundle.Run(assertOnError);
this.LastExitCode = result.ExitCode;
// Return the log file name.
return logFile;
}
public void Dispose()
{
string[] args = { "-burn.ignoredependencies=ALL" };
this.RunBundleWithArguments((int)MSIExec.MSIExecReturnCode.SUCCESS, MSIExec.MSIExecMode.Cleanup, args, assertOnError: false);
}
}
}