// 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 } } }