// 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.IO;
using System.Text;
using WixInternal.TestSupport;
public class MSIExec : TestTool
{
///
/// The expected exit code of the tool
///
public new MSIExecReturnCode ExpectedExitCode
{
get { return (MSIExecReturnCode)base.ExpectedExitCode; }
set { base.ExpectedExitCode = (int?)value; }
}
///
/// Mode of execution (install, uninstall, or repair)
///
public MSIExecMode ExecutionMode { get; set; }
///
/// Path to msi or ProductCode
///
public string Product { get; set; }
///
/// Logging Options
///
public MSIExecLoggingOptions LoggingOptions { get; set; }
///
/// Path to the log file
///
public string LogFile { get; set; }
///
/// Unattended mode - progress bar only
///
public bool Passive { get; set; }
///
/// Quiet mode, no user interaction
///
public bool Quiet { get; set; }
///
/// Sets user interface level
///
public MSIExecUserInterfaceLevel UserInterfaceLevel { get; set; }
///
/// Do not restart after the installation is complete
///
public bool NoRestart { get; set; }
///
/// Prompts the user for restart if necessary
///
public bool PromptRestart { get; set; }
///
/// Always restart the computer after installation
///
public bool ForceRestart { get; set; }
///
/// Other arguments.
///
public string OtherArguments { get; set; }
///
/// Constructor that uses the default location for MSIExec.
///
public MSIExec()
: this(Environment.SystemDirectory)
{
}
///
/// Constructor that accepts a path to the MSIExec location.
///
/// The directory of MSIExec.exe.
public MSIExec(string toolDirectory)
: base(Path.Combine(toolDirectory, "MSIExec.exe"))
{
this.SetDefaultArguments();
}
public override ExternalExecutableResult Run(bool assertOnError)
{
this.Arguments = this.GetArguments();
return base.Run(assertOnError);
}
///
/// Clears all of the assigned arguments and resets them to the default values.
///
public void SetDefaultArguments()
{
this.ExecutionMode = MSIExecMode.Install;
this.Product = String.Empty;
this.Quiet = true;
this.Passive = false;
this.UserInterfaceLevel = MSIExecUserInterfaceLevel.None;
this.NoRestart = true;
this.ForceRestart = false;
this.PromptRestart = false;
this.LogFile = String.Empty;
this.LoggingOptions = MSIExecLoggingOptions.Log_All_Information | MSIExecLoggingOptions.Verbose_Output | MSIExecLoggingOptions.Extra_Debugging_Information; // `/l*vx`
this.OtherArguments = String.Empty;
}
public string GetArguments()
{
var arguments = new StringBuilder();
// quiet
if (this.Quiet)
{
arguments.Append(" /quiet ");
}
// passive
if (this.Passive)
{
arguments.Append(" /passive ");
}
// UserInterfaceLevel
switch (this.UserInterfaceLevel)
{
case MSIExecUserInterfaceLevel.None:
arguments.Append(" /qn ");
break;
case MSIExecUserInterfaceLevel.Basic:
arguments.Append(" /qb ");
break;
case MSIExecUserInterfaceLevel.Reduced:
arguments.Append(" /qr ");
break;
case MSIExecUserInterfaceLevel.Full:
arguments.Append(" /qf ");
break;
}
// NoRestart
if (this.NoRestart)
{
arguments.Append(" /norestart ");
}
// PromptRestart
if (this.PromptRestart)
{
arguments.Append(" /promptrestart ");
}
// ForceRestart
if (this.ForceRestart)
{
arguments.Append(" /forcerestart ");
}
// Logging options
var loggingOptionsString = new StringBuilder();
if ((this.LoggingOptions & MSIExecLoggingOptions.Status_Messages) == MSIExecLoggingOptions.Status_Messages)
{
loggingOptionsString.Append("i");
}
if ((this.LoggingOptions & MSIExecLoggingOptions.Nonfatal_Warnings) == MSIExecLoggingOptions.Nonfatal_Warnings)
{
loggingOptionsString.Append("w");
}
if ((this.LoggingOptions & MSIExecLoggingOptions.All_Error_Messages) == MSIExecLoggingOptions.All_Error_Messages)
{
loggingOptionsString.Append("e");
}
if ((this.LoggingOptions & MSIExecLoggingOptions.Start_Up_Of_Actions) == MSIExecLoggingOptions.Start_Up_Of_Actions)
{
loggingOptionsString.Append("a");
}
if ((this.LoggingOptions & MSIExecLoggingOptions.Action_Specific_Records) == MSIExecLoggingOptions.Action_Specific_Records)
{
loggingOptionsString.Append("r");
}
if ((this.LoggingOptions & MSIExecLoggingOptions.User_Requests) == MSIExecLoggingOptions.User_Requests)
{
loggingOptionsString.Append("u");
}
if ((this.LoggingOptions & MSIExecLoggingOptions.Initial_UI_Parameters) == MSIExecLoggingOptions.Initial_UI_Parameters)
{
loggingOptionsString.Append("c");
}
if ((this.LoggingOptions & MSIExecLoggingOptions.OutOfMemory_Or_Fatal_Exit_Information) == MSIExecLoggingOptions.OutOfMemory_Or_Fatal_Exit_Information)
{
loggingOptionsString.Append("m");
}
if ((this.LoggingOptions & MSIExecLoggingOptions.OutOfDiskSpace_Messages) == MSIExecLoggingOptions.OutOfDiskSpace_Messages)
{
loggingOptionsString.Append("o");
}
if ((this.LoggingOptions & MSIExecLoggingOptions.Terminal_Properties) == MSIExecLoggingOptions.Terminal_Properties)
{
loggingOptionsString.Append("p");
}
if ((this.LoggingOptions & MSIExecLoggingOptions.Verbose_Output) == MSIExecLoggingOptions.Verbose_Output)
{
loggingOptionsString.Append("v");
}
if ((this.LoggingOptions & MSIExecLoggingOptions.Extra_Debugging_Information) == MSIExecLoggingOptions.Extra_Debugging_Information)
{
loggingOptionsString.Append("x");
}
if ((this.LoggingOptions & MSIExecLoggingOptions.Append_To_Existing_Log_File) == MSIExecLoggingOptions.Append_To_Existing_Log_File)
{
loggingOptionsString.Append("+");
}
if ((this.LoggingOptions & MSIExecLoggingOptions.Flush_Each_line) == MSIExecLoggingOptions.Flush_Each_line)
{
loggingOptionsString.Append("!");
}
if ((this.LoggingOptions & MSIExecLoggingOptions.Log_All_Information) == MSIExecLoggingOptions.Log_All_Information)
{
loggingOptionsString.Append("*");
}
// logfile and logging options
if (0 != loggingOptionsString.Length || !String.IsNullOrEmpty(this.LogFile))
{
arguments.Append(" /l");
if (0 != loggingOptionsString.Length)
{
arguments.AppendFormat("{0} ", loggingOptionsString);
}
if (!String.IsNullOrEmpty(this.LogFile))
{
arguments.AppendFormat(" \"{0}\" ", this.LogFile);
}
}
// OtherArguments
if (!String.IsNullOrEmpty(this.OtherArguments))
{
arguments.AppendFormat(" {0} ", this.OtherArguments);
}
// execution mode
switch (this.ExecutionMode)
{
case MSIExecMode.Install:
arguments.Append(" /package ");
break;
case MSIExecMode.AdministrativeInstall:
arguments.Append(" /a ");
break;
case MSIExecMode.Repair:
arguments.Append(" /fvomusa ");
break;
case MSIExecMode.Cleanup:
case MSIExecMode.Uninstall:
arguments.Append(" /uninstall ");
break;
};
// product
if (!String.IsNullOrEmpty(this.Product))
{
arguments.AppendFormat(" \"{0}\" ", this.Product);
}
return arguments.ToString();
}
///
/// Return codes from an MSI install or uninstall
///
///
/// Error codes indicative of success are:
/// ERROR_SUCCESS, ERROR_SUCCESS_REBOOT_INITIATED, and ERROR_SUCCESS_REBOOT_REQUIRED
///
public enum MSIExecReturnCode
{
///
/// ERROR_SUCCESS 0
/// Action completed successfully.
///
SUCCESS = 0,
///
/// ERROR_INVALID_DATA 13
/// The data is invalid.
///
ERROR_INVALID_DATA = 13,
///
/// ERROR_INVALID_PARAMETER 87
/// One of the parameters was invalid.
///
ERROR_INVALID_PARAMETER = 87,
///
/// ERROR_CALL_NOT_IMPLEMENTED 120
/// This value is returned when a custom action attempts to call a function that cannot be called from custom actions.
/// The function returns the value ERROR_CALL_NOT_IMPLEMENTED. Available beginning with Windows Installer version 3.0.
///
ERROR_CALL_NOT_IMPLEMENTED = 120,
///
/// ERROR_FILENAME_EXCED_RANGE 206
/// The filename or extension is too long.
///
ERROR_FILENAME_EXCED_RANGE = 206,
///
/// ERROR_APPHELP_BLOCK 1259
/// If Windows Installer determines a product may be incompatible with the current operating system,
/// it displays a dialog box informing the user and asking whether to try to install anyway.
/// This error code is returned if the user chooses not to try the installation.
///
ERROR_APPHELP_BLOCK = 1259,
///
/// ERROR_INSTALL_SERVICE_FAILURE 1601
/// The Windows Installer service could not be accessed.
/// Contact your support personnel to verify that the Windows Installer service is properly registered.
///
ERROR_INSTALL_SERVICE_FAILURE = 1601,
///
/// ERROR_INSTALL_USEREXIT 1602
/// The user cancels installation.
///
ERROR_INSTALL_USEREXIT = 1602,
///
/// ERROR_INSTALL_FAILURE 1603
/// A fatal error occurred during installation.
///
ERROR_INSTALL_FAILURE = 1603,
///
/// ERROR_INSTALL_SUSPEND 1604
/// Installation suspended, incomplete.
///
ERROR_INSTALL_SUSPEND = 1604,
///
/// ERROR_UNKNOWN_PRODUCT 1605
/// This action is only valid for products that are currently installed.
///
ERROR_UNKNOWN_PRODUCT = 1605,
///
/// ERROR_UNKNOWN_FEATURE 1606
/// The feature identifier is not registered.
///
ERROR_UNKNOWN_FEATURE = 1606,
///
/// ERROR_UNKNOWN_COMPONENT 1607
/// The component identifier is not registered.
///
ERROR_UNKNOWN_COMPONENT = 1607,
///
/// ERROR_UNKNOWN_PROPERTY 1608
/// This is an unknown property.
///
ERROR_UNKNOWN_PROPERTY = 1608,
///
/// ERROR_INVALID_HANDLE_STATE 1609
/// The handle is in an invalid state.
///
ERROR_INVALID_HANDLE_STATE = 1609,
///
/// ERROR_BAD_CONFIGURATION 1610
/// The configuration data for this product is corrupt. Contact your support personnel.
///
ERROR_BAD_CONFIGURATION = 1610,
///
/// ERROR_INDEX_ABSENT 1611
/// The component qualifier not present.
///
ERROR_INDEX_ABSENT = 1611,
/// ERROR_INSTALL_SOURCE_ABSENT 1612
/// The installation source for this product is not available.
/// Verify that the source exists and that you can access it.
///
ERROR_INSTALL_SOURCE_ABSENT = 1612,
///
/// ERROR_INSTALL_PACKAGE_VERSION 1613
/// This installation package cannot be installed by the Windows Installer service.
/// You must install a Windows service pack that contains a newer version of the Windows Installer service.
///
ERROR_INSTALL_PACKAGE_VERSION = 1613,
///
/// ERROR_PRODUCT_UNINSTALLED 1614
/// The product is uninstalled.
///
ERROR_PRODUCT_UNINSTALLED = 1614,
///
/// ERROR_BAD_QUERY_SYNTAX 1615
/// The SQL query syntax is invalid or unsupported.
///
ERROR_BAD_QUERY_SYNTAX = 1615,
///
/// ERROR_INVALID_FIELD 1616
/// The record field does not exist.
///
ERROR_INVALID_FIELD = 1616,
///
/// ERROR_INSTALL_ALREADY_RUNNING 1618
/// Another installation is already in progress. Complete that installation before proceeding with this install.
/// For information about the mutex, see _MSIExecute Mutex.
///
ERROR_INSTALL_ALREADY_RUNNING = 1618,
///
/// ERROR_INSTALL_PACKAGE_OPEN_FAILED 1619
/// This installation package could not be opened. Verify that the package exists and is accessible, or contact the
/// application vendor to verify that this is a valid Windows Installer package.
///
ERROR_INSTALL_PACKAGE_OPEN_FAILED = 1619,
///
/// ERROR_INSTALL_PACKAGE_INVALID 1620
/// This installation package could not be opened.
/// Contact the application vendor to verify that this is a valid Windows Installer package.
///
ERROR_INSTALL_PACKAGE_INVALID = 1620,
///
/// ERROR_INSTALL_UI_FAILURE 1621
/// There was an error starting the Windows Installer service user interface.
/// Contact your support personnel.
///
ERROR_INSTALL_UI_FAILURE = 1621,
///
/// ERROR_INSTALL_LOG_FAILURE 1622
/// There was an error opening installation log file.
/// Verify that the specified log file location exists and is writable.
///
ERROR_INSTALL_LOG_FAILURE = 1622,
///
/// ERROR_INSTALL_LANGUAGE_UNSUPPORTED 1623
/// This language of this installation package is not supported by your system.
///
ERROR_INSTALL_LANGUAGE_UNSUPPORTED = 1623,
///
/// ERROR_INSTALL_TRANSFORM_FAILURE 1624
/// There was an error applying transforms.
/// Verify that the specified transform paths are valid.
///
ERROR_INSTALL_TRANSFORM_FAILURE = 1624,
///
/// ERROR_INSTALL_PACKAGE_REJECTED 1625
/// This installation is forbidden by system policy.
/// Contact your system administrator.
///
ERROR_INSTALL_PACKAGE_REJECTED = 1625,
///
/// ERROR_FUNCTION_NOT_CALLED 1626
/// The function could not be executed.
///
ERROR_FUNCTION_NOT_CALLED = 1626,
///
/// ERROR_FUNCTION_FAILED 1627
/// The function failed during execution.
///
ERROR_FUNCTION_FAILED = 1627,
///
/// ERROR_INVALID_TABLE 1628
/// An invalid or unknown table was specified.
///
ERROR_INVALID_TABLE = 1628,
///
/// ERROR_DATATYPE_MISMATCH 1629
/// The data supplied is the wrong type.
///
ERROR_DATATYPE_MISMATCH = 1629,
///
/// ERROR_UNSUPPORTED_TYPE 1630
/// Data of this type is not supported.
///
ERROR_UNSUPPORTED_TYPE = 1630,
///
/// ERROR_CREATE_FAILED 1631
/// The Windows Installer service failed to start.
/// Contact your support personnel.
///
ERROR_CREATE_FAILED = 1631,
///
/// ERROR_INSTALL_TEMP_UNWRITABLE 1632
/// The Temp folder is either full or inaccessible.
/// Verify that the Temp folder exists and that you can write to it.
///
ERROR_INSTALL_TEMP_UNWRITABLE = 1632,
///
/// ERROR_INSTALL_PLATFORM_UNSUPPORTED 1633
/// This installation package is not supported on this platform. Contact your application vendor.
ERROR_INSTALL_PLATFORM_UNSUPPORTED = 1633,
///
/// ERROR_INSTALL_NOTUSED 1634
/// Component is not used on this machine.
///
ERROR_INSTALL_NOTUSED = 1634,
///
/// ERROR_PATCH_PACKAGE_OPEN_FAILED 1635
/// This patch package could not be opened. Verify that the patch package exists and is accessible,
/// or contact the application vendor to verify that this is a valid Windows Installer patch package.
///
ERROR_PATCH_PACKAGE_OPEN_FAILED = 1635,
///
/// ERROR_PATCH_PACKAGE_INVALID 1636
/// This patch package could not be opened.
/// Contact the application vendor to verify that this is a valid Windows Installer patch package.
///
ERROR_PATCH_PACKAGE_INVALID = 1636,
///
/// ERROR_PATCH_PACKAGE_UNSUPPORTED 1637
/// This patch package cannot be processed by the Windows Installer service.
/// You must install a Windows service pack that contains a newer version of the Windows Installer service.
///
ERROR_PATCH_PACKAGE_UNSUPPORTED = 1637,
///
/// ERROR_PRODUCT_VERSION 1638
/// Another version of this product is already installed.
/// Installation of this version cannot continue. To configure or remove the existing version of this product,
/// use Add/Remove Programs in Control Panel.
///
ERROR_PRODUCT_VERSION = 1638,
///
/// ERROR_INVALID_COMMAND_LINE 1639
/// Invalid command line argument.
/// Consult the Windows Installer SDK for detailed command-line help.
///
ERROR_INVALID_COMMAND_LINE = 1639,
///
/// ERROR_INSTALL_REMOTE_DISALLOWED 1640
/// The current user is not permitted to perform installations from a client session of a server running the
/// Terminal Server role service.
///
ERROR_INSTALL_REMOTE_DISALLOWED = 1640,
///
/// ERROR_SUCCESS_REBOOT_INITIATED 1641
/// The installer has initiated a restart.
/// This message is indicative of a success.
///
ERROR_SUCCESS_REBOOT_INITIATED = 1641,
///
/// ERROR_PATCH_TARGET_NOT_FOUND 1642
/// The installer cannot install the upgrade patch because the program being upgraded may be missing or the
/// upgrade patch updates a different version of the program.
/// Verify that the program to be upgraded exists on your computer and that you have the correct upgrade patch.
///
ERROR_PATCH_TARGET_NOT_FOUND = 1642,
///
/// ERROR_PATCH_PACKAGE_REJECTED 1643
/// The patch package is not permitted by system policy.
///
ERROR_PATCH_PACKAGE_REJECTED = 1643,
///
/// ERROR_INSTALL_TRANSFORM_REJECTED 1644
/// One or more customizations are not permitted by system policy.
///
ERROR_INSTALL_TRANSFORM_REJECTED = 1644,
///
/// ERROR_INSTALL_REMOTE_PROHIBITED 1645
/// Windows Installer does not permit installation from a Remote Desktop Connection.
///
ERROR_INSTALL_REMOTE_PROHIBITED = 1645,
///
/// ERROR_PATCH_REMOVAL_UNSUPPORTED 1646
/// The patch package is not a removable patch package. Available beginning with Windows Installer version 3.0.
///
ERROR_PATCH_REMOVAL_UNSUPPORTED = 1646,
///
/// ERROR_UNKNOWN_PATCH 1647
/// The patch is not applied to this product. Available beginning with Windows Installer version 3.0.
///
ERROR_UNKNOWN_PATCH = 1647,
///
/// ERROR_PATCH_NO_SEQUENCE 1648
/// No valid sequence could be found for the set of patches. Available beginning with Windows Installer version 3.0.
///
ERROR_PATCH_NO_SEQUENCE = 1648,
///
/// ERROR_PATCH_REMOVAL_DISALLOWED 1649
/// Patch removal was disallowed by policy. Available beginning with Windows Installer version 3.0.
ERROR_PATCH_REMOVAL_DISALLOWED = 1649,
///
/// ERROR_INVALID_PATCH_XML = 1650
/// The XML patch data is invalid. Available beginning with Windows Installer version 3.0.
///
ERROR_INVALID_PATCH_XML = 1650,
///
/// ERROR_PATCH_MANAGED_ADVERTISED_PRODUCT 1651
/// Administrative user failed to apply patch for a per-user managed or a per-machine application that is in advertise state.
/// Available beginning with Windows Installer version 3.0.
ERROR_PATCH_MANAGED_ADVERTISED_PRODUCT = 1651,
///
/// ERROR_INSTALL_SERVICE_SAFEBOOT 1652
/// Windows Installer is not accessible when the computer is in Safe Mode.
/// Exit Safe Mode and try again or try using System Restore to return your computer to a previous state.
/// Available beginning with Windows Installer version 4.0.
///
ERROR_INSTALL_SERVICE_SAFEBOOT = 1652,
///
/// ERROR_ROLLBACK_DISABLED 1653
/// Could not perform a multiple-package transaction because rollback has been disabled.
/// Multiple-Package Installations cannot run if rollback is disabled. Available beginning with Windows Installer version 4.5.
///
ERROR_ROLLBACK_DISABLED = 1653,
///
/// ERROR_SUCCESS_REBOOT_REQUIRED 3010
/// A restart is required to complete the install. This message is indicative of a success.
/// This does not include installs where the ForceReboot action is run.
///
ERROR_SUCCESS_REBOOT_REQUIRED = 3010,
///
/// ERROR_SUCCESS_REBOOT_REQUIRED 3017
/// The requested operation failed. A system reboot is required to roll back changes made.
///
ERROR_FAIL_REBOOT_REQUIRED = 3017,
}
///
/// Modes of operations for MSIExec; install, administrator install, uninstall .. etc
///
public enum MSIExecMode
{
///
/// Installs or configures a product
///
Install = 0,
///
/// Administrative install - Installs a product on the network
///
AdministrativeInstall,
///
/// Uninstalls the product
///
Uninstall,
///
/// Repairs a product
///
Repair,
///
/// Modifies a product
///
Modify,
///
/// Uninstalls the product as part of cleanup
///
Cleanup,
///
/// No action automatically added to arguments
///
Custom,
}
///
/// User interfave levels
///
public enum MSIExecUserInterfaceLevel
{
///
/// No UI
///
None = 0,
///
/// Basic UI
///
Basic,
///
/// Reduced UI
///
Reduced,
///
/// Full UI (default)
///
Full
}
///
/// Logging options
///
[Flags]
public enum MSIExecLoggingOptions
{
Status_Messages = 0x0001,
Nonfatal_Warnings = 0x0002,
All_Error_Messages = 0x0004,
Start_Up_Of_Actions = 0x0008,
Action_Specific_Records = 0x0010,
User_Requests = 0x0020,
Initial_UI_Parameters = 0x0040,
OutOfMemory_Or_Fatal_Exit_Information = 0x0080,
OutOfDiskSpace_Messages = 0x0100,
Terminal_Properties = 0x0200,
Verbose_Output = 0x0400,
Append_To_Existing_Log_File = 0x0800,
Flush_Each_line = 0x1000,
Extra_Debugging_Information = 0x2000,
Log_All_Information = 0x4000,
VOICEWARMUP = 0x0FFF
}
}
}