Ejemplo n.º 1
0
        public bool run_action(ChocolateyConfiguration configuration, PackageResult packageResult, CommandNameType command)
        {
            var installerRun = false;

            var packageDirectory = packageResult.InstallLocation;

            if (packageDirectory.is_equal_to(ApplicationParameters.InstallLocation) || packageDirectory.is_equal_to(ApplicationParameters.PackagesLocation))
            {
                packageResult.Messages.Add(
                    new ResultMessage(
                        ResultType.Error,
                        "Install location is not specific enough, cannot run PowerShell script:{0} Erroneous install location captured as '{1}'".format_with(Environment.NewLine, packageResult.InstallLocation)
                        )
                    );

                return(false);
            }

            if (!_fileSystem.directory_exists(packageDirectory))
            {
                packageResult.Messages.Add(new ResultMessage(ResultType.Error, "Package install not found:'{0}'".format_with(packageDirectory)));
                return(installerRun);
            }

            var chocoPowerShellScript = get_script_for_action(packageResult, command);

            if (!string.IsNullOrEmpty(chocoPowerShellScript))
            {
                var failure = false;
                var package = packageResult.Package;
                prepare_powershell_environment(package, configuration, packageDirectory);

                this.Log().Debug(ChocolateyLoggers.Important, "Contents of '{0}':".format_with(chocoPowerShellScript));
                string chocoPowerShellScriptContents = _fileSystem.read_file(chocoPowerShellScript);
                // leave this way, doesn't take it through formatting.
                this.Log().Debug(() => chocoPowerShellScriptContents.escape_curly_braces());

                bool shouldRun = !configuration.PromptForConfirmation;

                if (!shouldRun)
                {
                    this.Log().Info(ChocolateyLoggers.Important, () => "The package {0} wants to run '{1}'.".format_with(package.Id, _fileSystem.get_file_name(chocoPowerShellScript)));
                    this.Log().Info(ChocolateyLoggers.Important, () => "Note: If you don't run this script, the installation will fail.");
                    this.Log().Info(ChocolateyLoggers.Important, () => @"Note: To confirm automatically next time, use '-y' or consider:");
                    this.Log().Info(ChocolateyLoggers.Important, () => @"choco feature enable -n allowGlobalConfirmation");

                    var selection = InteractivePrompt.prompt_for_confirmation(@"Do you want to run the script?",
                                                                              new[] { "yes", "no", "print" },
                                                                              defaultChoice: null,
                                                                              requireAnswer: true,
                                                                              allowShortAnswer: true,
                                                                              shortPrompt: true
                                                                              );

                    if (selection.is_equal_to("print"))
                    {
                        this.Log().Info(ChocolateyLoggers.Important, "------ BEGIN SCRIPT ------");
                        this.Log().Info(() => "{0}{1}{0}".format_with(Environment.NewLine, chocoPowerShellScriptContents.escape_curly_braces()));
                        this.Log().Info(ChocolateyLoggers.Important, "------- END SCRIPT -------");
                        selection = InteractivePrompt.prompt_for_confirmation(@"Do you want to run this script?",
                                                                              new[] { "yes", "no" },
                                                                              defaultChoice: null,
                                                                              requireAnswer: true,
                                                                              allowShortAnswer: true,
                                                                              shortPrompt: true
                                                                              );
                    }

                    if (selection.is_equal_to("yes"))
                    {
                        shouldRun = true;
                    }
                    if (selection.is_equal_to("no"))
                    {
                        //MSI ERROR_INSTALL_USEREXIT - 1602 - https://support.microsoft.com/en-us/kb/304888 / https://msdn.microsoft.com/en-us/library/aa376931.aspx
                        //ERROR_INSTALL_CANCEL - 15608 - https://msdn.microsoft.com/en-us/library/windows/desktop/ms681384.aspx
                        Environment.ExitCode = 15608;
                        packageResult.Messages.Add(new ResultMessage(ResultType.Error, "User canceled powershell portion of installation for '{0}'.{1} Specify -n to skip automated script actions.".format_with(chocoPowerShellScript, Environment.NewLine)));
                    }
                }

                if (shouldRun)
                {
                    installerRun = true;

                    if (configuration.Features.UsePowerShellHost)
                    {
                        add_assembly_resolver();
                    }

                    var result = new PowerShellExecutionResults
                    {
                        ExitCode = -1
                    };

                    try
                    {
                        result = configuration.Features.UsePowerShellHost
                                    ? Execute.with_timeout(configuration.CommandExecutionTimeoutSeconds).command(() => run_host(configuration, chocoPowerShellScript, null), result)
                                    : run_external_powershell(configuration, chocoPowerShellScript);
                    }
                    catch (Exception ex)
                    {
                        this.Log().Error(ex.Message.escape_curly_braces());
                        result.ExitCode = 1;
                    }

                    if (configuration.Features.UsePowerShellHost)
                    {
                        remove_assembly_resolver();
                    }

                    if (result.StandardErrorWritten && configuration.Features.FailOnStandardError)
                    {
                        failure = true;
                    }
                    else if (result.StandardErrorWritten && result.ExitCode == 0)
                    {
                        this.Log().Warn(
                            () =>
                            @"Only an exit code of non-zero will fail the package by default. Set 
 `--failonstderr` if you want error messages to also fail a script. See 
 `choco -h` for details.");
                    }


                    if (result.ExitCode != 0)
                    {
                        Environment.ExitCode   = result.ExitCode;
                        packageResult.ExitCode = result.ExitCode;
                    }

                    // 0 - most widely used success exit code
                    // MSI valid exit codes
                    // 1605 - (uninstall) - the product is not found, could have already been uninstalled
                    // 1614 (uninstall) - the product is uninstalled
                    // 1641 - restart initiated
                    // 3010 - restart required
                    var validExitCodes = new List <int> {
                        0, 1605, 1614, 1641, 3010
                    };
                    if (!validExitCodes.Contains(result.ExitCode))
                    {
                        failure = true;
                    }

                    if (!configuration.Features.UsePackageExitCodes)
                    {
                        Environment.ExitCode = failure ? 1 : 0;
                    }

                    if (failure)
                    {
                        packageResult.Messages.Add(new ResultMessage(ResultType.Error, "Error while running '{0}'.{1} See log for details.".format_with(chocoPowerShellScript, Environment.NewLine)));
                    }
                    packageResult.Messages.Add(new ResultMessage(ResultType.Note, "Ran '{0}'".format_with(chocoPowerShellScript)));
                }
            }

            return(installerRun);
        }
Ejemplo n.º 2
0
        public bool run_action(ChocolateyConfiguration configuration, PackageResult packageResult, CommandNameType command)
        {
            var installerRun = false;

            var file = "chocolateyInstall.ps1";

            switch (command)
            {
            case CommandNameType.uninstall:
                file = "chocolateyUninstall.ps1";
                break;
            }

            var packageDirectory = packageResult.InstallLocation;

            if (packageDirectory.is_equal_to(ApplicationParameters.InstallLocation) || packageDirectory.is_equal_to(ApplicationParameters.PackagesLocation))
            {
                packageResult.Messages.Add(
                    new ResultMessage(
                        ResultType.Error,
                        "Install location is not specific enough, cannot run PowerShell script:{0} Erroneous install location captured as '{1}'".format_with(Environment.NewLine, packageResult.InstallLocation)
                        )
                    );

                return(false);
            }

            if (!_fileSystem.directory_exists(packageDirectory))
            {
                packageResult.Messages.Add(new ResultMessage(ResultType.Error, "Package install not found:'{0}'".format_with(packageDirectory)));
                return(installerRun);
            }

            var powershellScript = _fileSystem.get_files(packageDirectory, file, SearchOption.AllDirectories);

            if (powershellScript.Count() != 0)
            {
                var chocoPowerShellScript = powershellScript.FirstOrDefault();

                var failure = false;

                var package = packageResult.Package;
                Environment.SetEnvironmentVariable(ApplicationParameters.ChocolateyInstallEnvironmentVariableName, ApplicationParameters.InstallLocation);
                Environment.SetEnvironmentVariable("CHOCOLATEY_VERSION", configuration.Information.ChocolateyVersion);
                Environment.SetEnvironmentVariable("CHOCOLATEY_VERSION_PRODUCT", configuration.Information.ChocolateyProductVersion);
                Environment.SetEnvironmentVariable("OS_PLATFORM", configuration.Information.PlatformType.get_description_or_value());
                Environment.SetEnvironmentVariable("OS_VERSION", configuration.Information.PlatformVersion.to_string());
                Environment.SetEnvironmentVariable("OS_NAME", configuration.Information.PlatformName.to_string());
                // experimental until we know if this value returns correctly based on the OS and not the current process.
                Environment.SetEnvironmentVariable("OS_IS64BIT", configuration.Information.Is64Bit ? "true" : "false");
                Environment.SetEnvironmentVariable("IS_ADMIN", configuration.Information.IsUserAdministrator ? "true" : "false");
                Environment.SetEnvironmentVariable("IS_PROCESSELEVATED", configuration.Information.IsProcessElevated ? "true" : "false");
                Environment.SetEnvironmentVariable("chocolateyPackageName", package.Id);
                Environment.SetEnvironmentVariable("packageName", package.Id);
                Environment.SetEnvironmentVariable("chocolateyPackageVersion", package.Version.to_string());
                Environment.SetEnvironmentVariable("packageVersion", package.Version.to_string());
                Environment.SetEnvironmentVariable("chocolateyPackageFolder", packageDirectory);
                Environment.SetEnvironmentVariable("packageFolder", packageDirectory);
                Environment.SetEnvironmentVariable("installArguments", configuration.InstallArguments);
                Environment.SetEnvironmentVariable("installerArguments", configuration.InstallArguments);
                Environment.SetEnvironmentVariable("chocolateyInstallArguments", configuration.InstallArguments);
                Environment.SetEnvironmentVariable("packageParameters", configuration.PackageParameters);
                Environment.SetEnvironmentVariable("chocolateyPackageParameters", configuration.PackageParameters);
                if (configuration.ForceX86)
                {
                    Environment.SetEnvironmentVariable("chocolateyForceX86", "true");
                }
                if (configuration.OverrideArguments)
                {
                    Environment.SetEnvironmentVariable("chocolateyInstallOverride", "true");
                }

                Environment.SetEnvironmentVariable("TEMP", configuration.CacheLocation);

                //verify how not silent is passed
                //if (configuration.NotSilent)
                //{
                //    Environment.SetEnvironmentVariable("installerArguments", "  ");
                //    Environment.SetEnvironmentVariable("chocolateyInstallOverride", "true");
                //}
                if (configuration.Debug)
                {
                    Environment.SetEnvironmentVariable("ChocolateyEnvironmentDebug", "true");
                }
                if (configuration.Verbose)
                {
                    Environment.SetEnvironmentVariable("ChocolateyEnvironmentVerbose", "true");
                }
                //todo:if (configuration.NoOutput)
                //{
                //    Environment.SetEnvironmentVariable("ChocolateyEnvironmentQuiet","true");
                //}

                this.Log().Debug(ChocolateyLoggers.Important, "Contents of '{0}':".format_with(chocoPowerShellScript));
                string chocoPowerShellScriptContents = _fileSystem.read_file(chocoPowerShellScript);
                this.Log().Debug(chocoPowerShellScriptContents.escape_curly_braces());

                bool shouldRun = !configuration.PromptForConfirmation;

                if (!shouldRun)
                {
                    this.Log().Info(ChocolateyLoggers.Important, () => "The package {0} wants to run '{1}'.".format_with(package.Id, _fileSystem.get_file_name(chocoPowerShellScript)));
                    this.Log().Info(ChocolateyLoggers.Important, () => "Note: If you don't run this script, the installation will fail.");

                    var selection = InteractivePrompt.prompt_for_confirmation(@"Do you want to run the script?", new[] { "yes", "no", "print" }, defaultChoice: null, requireAnswer: true);

                    if (selection.is_equal_to("print"))
                    {
                        this.Log().Info(ChocolateyLoggers.Important, "------ BEGIN SCRIPT ------");
                        this.Log().Info(() => "{0}{1}{0}".format_with(Environment.NewLine, chocoPowerShellScriptContents.escape_curly_braces()));
                        this.Log().Info(ChocolateyLoggers.Important, "------- END SCRIPT -------");
                        selection = InteractivePrompt.prompt_for_confirmation(@"Do you want to run this script?", new[] { "yes", "no" }, defaultChoice: null, requireAnswer: true);
                    }

                    if (selection.is_equal_to("yes"))
                    {
                        shouldRun = true;
                    }
                    if (selection.is_equal_to("no"))
                    {
                        Environment.ExitCode = 1;
                        packageResult.Messages.Add(new ResultMessage(ResultType.Error, "User cancelled powershell portion of installation for '{0}'.{1} Use skip to install without run.".format_with(powershellScript.FirstOrDefault(), Environment.NewLine)));
                    }
                }

                if (shouldRun)
                {
                    installerRun = true;
                    var exitCode = PowershellExecutor.execute(
                        wrap_script_with_module(chocoPowerShellScript, configuration),
                        _fileSystem,
                        configuration.CommandExecutionTimeoutSeconds,
                        (s, e) =>
                    {
                        if (string.IsNullOrWhiteSpace(e.Data))
                        {
                            return;
                        }
                        //inspect for different streams
                        if (e.Data.StartsWith("DEBUG:"))
                        {
                            this.Log().Debug(() => " " + e.Data);
                        }
                        else if (e.Data.StartsWith("WARNING:"))
                        {
                            this.Log().Warn(() => " " + e.Data);
                        }
                        else if (e.Data.StartsWith("VERBOSE:"))
                        {
                            this.Log().Info(ChocolateyLoggers.Verbose, () => " " + e.Data);
                        }
                        else
                        {
                            this.Log().Info(() => " " + e.Data);
                        }
                    },
                        (s, e) =>
                    {
                        if (string.IsNullOrWhiteSpace(e.Data))
                        {
                            return;
                        }
                        failure = true;
                        this.Log().Error(() => " " + e.Data);
                    });

                    if (failure)
                    {
                        Environment.ExitCode = exitCode;
                        packageResult.Messages.Add(new ResultMessage(ResultType.Error, "Error while running '{0}'.{1} See log for details.".format_with(powershellScript.FirstOrDefault(), Environment.NewLine)));
                    }
                    packageResult.Messages.Add(new ResultMessage(ResultType.Note, "Ran '{0}'".format_with(chocoPowerShellScript)));
                }
            }

            return(installerRun);
        }
Ejemplo n.º 3
0
        public bool run_action(ChocolateyConfiguration configuration, PackageResult packageResult, CommandNameType command)
        {
            var installerRun = false;

            var file = "chocolateyInstall.ps1";
            switch (command)
            {
                case CommandNameType.uninstall:
                    file = "chocolateyUninstall.ps1";
                    break;
            }

            var packageDirectory = packageResult.InstallLocation;

            if (!_fileSystem.directory_exists(packageDirectory))
            {
                packageResult.Messages.Add(new ResultMessage(ResultType.Error, "Package install not found:'{0}'".format_with(packageDirectory)));
                return installerRun;
            }

            var powershellScript = _fileSystem.get_files(packageDirectory, file, SearchOption.AllDirectories);
            if (powershellScript.Count != 0)
            {
                var chocoPowerShellScript = powershellScript.FirstOrDefault();

                var failure = false;

                var package = packageResult.Package;
                Environment.SetEnvironmentVariable("CHOCOLATEY_VERSION", configuration.Information.ChocolateyVersion);
                Environment.SetEnvironmentVariable("OS_TYPE", configuration.Information.PlatformType.get_description_or_value());
                Environment.SetEnvironmentVariable("OS_VERSION", configuration.Information.PlatformVersion.to_string());
                // experimental until we know if this value returns correctly based on the OS and not the current process.
                Environment.SetEnvironmentVariable("OS_IS64BIT", configuration.Information.Is64Bit ? "true":"false");
                Environment.SetEnvironmentVariable("chocolateyPackageName", package.Id);
                Environment.SetEnvironmentVariable("chocolateyPackageVersion", package.Version.to_string());
                Environment.SetEnvironmentVariable("chocolateyPackageFolder", ApplicationParameters.PackagesLocation);
                Environment.SetEnvironmentVariable("installerArguments", configuration.InstallArguments);
                Environment.SetEnvironmentVariable("chocolateyPackageParameters", configuration.PackageParameters);
                if (configuration.ForceX86)
                {
                    Environment.SetEnvironmentVariable("chocolateyForceX86", "true");
                }
                if (configuration.OverrideArguments)
                {
                    Environment.SetEnvironmentVariable("chocolateyInstallOverride", "true");
                }

                if (!string.IsNullOrWhiteSpace(configuration.CacheLocation))
                {
                    //refactor - this is possibly temporary until we get all things running Posh into here
                    Environment.SetEnvironmentVariable("TEMP", configuration.CacheLocation);
                }

                //verify how not silent is passed
                //if (configuration.NotSilent)
                //{
                //    Environment.SetEnvironmentVariable("installerArguments", "  ");
                //    Environment.SetEnvironmentVariable("chocolateyInstallOverride", "true");
                //}
                if (configuration.Debug)
                {
                    Environment.SetEnvironmentVariable("ChocolateyEnvironmentDebug", "true");
                }
                if (configuration.Verbose)
                {
                    Environment.SetEnvironmentVariable("ChocolateyEnvironmentVerbose", "true");
                }
                //todo:if (configuration.NoOutput)
                //{
                //    Environment.SetEnvironmentVariable("ChocolateyEnvironmentQuiet","true");
                //}

                this.Log().Debug(ChocolateyLoggers.Important, "Contents of '{0}':".format_with(chocoPowerShellScript));
                string chocoPowerShellScriptContents = _fileSystem.read_file(chocoPowerShellScript).escape_curly_braces();
                this.Log().Debug(chocoPowerShellScriptContents);

                bool shouldRun = !configuration.PromptForConfirmation;

                if (!shouldRun)
                {
                    this.Log().Info(ChocolateyLoggers.Important, () => " Found '{0}':".format_with(_fileSystem.get_file_name(chocoPowerShellScript)));
                    this.Log().Info(() => "{0}{1}{0}".format_with(Environment.NewLine, chocoPowerShellScriptContents));
                    var selection = InteractivePrompt.prompt_for_confirmation(" Do you want to run the script?", new[] {"yes", "no", "skip"}, "no", requireAnswer: true);
                    if (selection.is_equal_to("yes")) shouldRun = true;
                    if (selection.is_equal_to("no"))
                    {
                        Environment.ExitCode = 1;
                        packageResult.Messages.Add(new ResultMessage(ResultType.Error, "User cancelled powershell portion of installation for '{0}'.{1} Use skip to install without run.".format_with(powershellScript.FirstOrDefault(), Environment.NewLine)));
                    }
                }

                if (shouldRun)
                {
                    installerRun = true;
                    var exitCode = PowershellExecutor.execute(
                        wrap_command_with_module(chocoPowerShellScript),
                        _fileSystem,
                        configuration.CommandExecutionTimeoutSeconds,
                        (s, e) =>
                            {
                                if (string.IsNullOrWhiteSpace(e.Data)) return;
                                //inspect for different streams
                                if (e.Data.StartsWith("DEBUG:"))
                                {
                                    this.Log().Debug(() => " " + e.Data);
                                }
                                else if (e.Data.StartsWith("WARNING:"))
                                {
                                    this.Log().Warn(() => " " + e.Data);
                                }
                                else if (e.Data.StartsWith("VERBOSE:"))
                                {
                                    this.Log().Info(ChocolateyLoggers.Verbose,() => " " + e.Data);
                                }
                                else
                                {
                                    this.Log().Info(() => " " + e.Data);
                                }
                            },
                        (s, e) =>
                            {
                                if (string.IsNullOrWhiteSpace(e.Data)) return;
                                failure = true;
                                this.Log().Error(() => " " + e.Data);
                            });

                    if (failure)
                    {
                        Environment.ExitCode = exitCode;
                        packageResult.Messages.Add(new ResultMessage(ResultType.Error, "Error while running '{0}'.{1} See log for details.".format_with(powershellScript.FirstOrDefault(), Environment.NewLine)));
                    }
                    packageResult.Messages.Add(new ResultMessage(ResultType.Note, "Ran '{0}'".format_with(powershellScript)));
                }
            }

            return installerRun;
        }
Ejemplo n.º 4
0
        public bool run_action(ChocolateyConfiguration configuration, PackageResult packageResult, CommandNameType command)
        {
            var installerRun = false;

            var packageDirectory = packageResult.InstallLocation;

            if (packageDirectory.is_equal_to(ApplicationParameters.InstallLocation) || packageDirectory.is_equal_to(ApplicationParameters.PackagesLocation))
            {
                packageResult.Messages.Add(
                    new ResultMessage(
                        ResultType.Error,
                        "Install location is not specific enough, cannot run PowerShell script:{0} Erroneous install location captured as '{1}'".format_with(Environment.NewLine, packageResult.InstallLocation)
                        )
                    );

                return(false);
            }

            if (!_fileSystem.directory_exists(packageDirectory))
            {
                packageResult.Messages.Add(new ResultMessage(ResultType.Error, "Package install not found:'{0}'".format_with(packageDirectory)));
                return(installerRun);
            }

            var chocoPowerShellScript = get_script_for_action(packageResult, command);

            if (!string.IsNullOrEmpty(chocoPowerShellScript))
            {
                var failure = false;

                ConfigurationBuilder.set_environment_variables(configuration);

                var package = packageResult.Package;
                Environment.SetEnvironmentVariable("chocolateyPackageName", package.Id);
                Environment.SetEnvironmentVariable("packageName", package.Id);
                Environment.SetEnvironmentVariable("chocolateyPackageVersion", package.Version.to_string());
                Environment.SetEnvironmentVariable("packageVersion", package.Version.to_string());
                Environment.SetEnvironmentVariable("chocolateyPackageFolder", packageDirectory);
                Environment.SetEnvironmentVariable("packageFolder", packageDirectory);
                Environment.SetEnvironmentVariable("installArguments", configuration.InstallArguments);
                Environment.SetEnvironmentVariable("installerArguments", configuration.InstallArguments);
                Environment.SetEnvironmentVariable("chocolateyInstallArguments", configuration.InstallArguments);
                Environment.SetEnvironmentVariable("packageParameters", configuration.PackageParameters);
                Environment.SetEnvironmentVariable("chocolateyPackageParameters", configuration.PackageParameters);

                if (configuration.ForceX86)
                {
                    Environment.SetEnvironmentVariable("chocolateyForceX86", "true");
                }
                if (configuration.OverrideArguments)
                {
                    Environment.SetEnvironmentVariable("chocolateyInstallOverride", "true");
                }

                if (configuration.NotSilent)
                {
                    Environment.SetEnvironmentVariable("chocolateyInstallOverride", "true");
                }

                //todo:if (configuration.NoOutput)
                //{
                //    Environment.SetEnvironmentVariable("ChocolateyEnvironmentQuiet","true");
                //}

                if (package.IsDownloadCacheAvailable)
                {
                    foreach (var downloadCache in package.DownloadCache.or_empty_list_if_null())
                    {
                        var urlKey = CryptoHashProvider.hash_value(downloadCache.OriginalUrl, CryptoHashProviderType.Sha256).Replace("=", string.Empty);
                        Environment.SetEnvironmentVariable("CacheFile_{0}".format_with(urlKey), downloadCache.FileName);
                        Environment.SetEnvironmentVariable("CacheChecksum_{0}".format_with(urlKey), downloadCache.Checksum);
                        Environment.SetEnvironmentVariable("CacheChecksumType_{0}".format_with(urlKey), "sha512");
                    }
                }

                this.Log().Debug(ChocolateyLoggers.Important, "Contents of '{0}':".format_with(chocoPowerShellScript));
                string chocoPowerShellScriptContents = _fileSystem.read_file(chocoPowerShellScript);
                this.Log().Debug(chocoPowerShellScriptContents.escape_curly_braces());

                bool shouldRun = !configuration.PromptForConfirmation;

                if (!shouldRun)
                {
                    this.Log().Info(ChocolateyLoggers.Important, () => "The package {0} wants to run '{1}'.".format_with(package.Id, _fileSystem.get_file_name(chocoPowerShellScript)));
                    this.Log().Info(ChocolateyLoggers.Important, () => "Note: If you don't run this script, the installation will fail.");
                    this.Log().Info(ChocolateyLoggers.Important, () => @"Note: To confirm automatically next time, use '-y' or consider setting 
 'allowGlobalConfirmation'. Run 'choco feature -h' for more details.");

                    var selection = InteractivePrompt.prompt_for_confirmation(@"Do you want to run the script?",
                                                                              new[] { "yes", "no", "print" },
                                                                              defaultChoice: null,
                                                                              requireAnswer: true,
                                                                              allowShortAnswer: true,
                                                                              shortPrompt: true
                                                                              );

                    if (selection.is_equal_to("print"))
                    {
                        this.Log().Info(ChocolateyLoggers.Important, "------ BEGIN SCRIPT ------");
                        this.Log().Info(() => "{0}{1}{0}".format_with(Environment.NewLine, chocoPowerShellScriptContents.escape_curly_braces()));
                        this.Log().Info(ChocolateyLoggers.Important, "------- END SCRIPT -------");
                        selection = InteractivePrompt.prompt_for_confirmation(@"Do you want to run this script?",
                                                                              new[] { "yes", "no" },
                                                                              defaultChoice: null,
                                                                              requireAnswer: true,
                                                                              allowShortAnswer: true,
                                                                              shortPrompt: true
                                                                              );
                    }

                    if (selection.is_equal_to("yes"))
                    {
                        shouldRun = true;
                    }
                    if (selection.is_equal_to("no"))
                    {
                        Environment.ExitCode = 1;
                        packageResult.Messages.Add(new ResultMessage(ResultType.Error, "User cancelled powershell portion of installation for '{0}'.{1} Specify -n to skip automated script actions.".format_with(chocoPowerShellScript, Environment.NewLine)));
                    }
                }

                if (shouldRun)
                {
                    installerRun = true;

                    if (configuration.Features.UsePowerShellHost)
                    {
                        add_assembly_resolver();
                    }

                    var result = new PowerShellExecutionResults
                    {
                        ExitCode = -1
                    };

                    try
                    {
                        result = configuration.Features.UsePowerShellHost
                                    ? Execute.with_timeout(configuration.CommandExecutionTimeoutSeconds).command(() => run_host(configuration, chocoPowerShellScript), result)
                                    : run_external_powershell(configuration, chocoPowerShellScript);
                    }
                    catch (Exception ex)
                    {
                        this.Log().Error(ex.Message.escape_curly_braces());
                        result.ExitCode = -1;
                    }

                    if (configuration.Features.UsePowerShellHost)
                    {
                        remove_assembly_resolver();
                    }

                    if (result.StandardErrorWritten && configuration.Features.FailOnStandardError)
                    {
                        failure = true;
                    }
                    else if (result.StandardErrorWritten && result.ExitCode == 0)
                    {
                        this.Log().Warn(
                            () =>
                            @"Only an exit code of non-zero will fail the package by default. Set 
 `--failonstderr` if you want error messages to also fail a script. See 
 `choco -h` for details.");
                    }


                    if (result.ExitCode != 0)
                    {
                        Environment.ExitCode   = result.ExitCode;
                        packageResult.ExitCode = result.ExitCode;
                    }

                    // 0 - most widely used success exit code
                    // MSI valid exit codes
                    // 1605 - (uninstall) - the product is not found, could have already been uninstalled
                    // 1614 (uninstall) - the product is uninstalled
                    // 1641 - restart initiated
                    // 3010 - restart required
                    var validExitCodes = new List <int> {
                        0, 1605, 1614, 1641, 3010
                    };
                    if (!validExitCodes.Contains(result.ExitCode))
                    {
                        failure = true;
                    }

                    if (failure)
                    {
                        packageResult.Messages.Add(new ResultMessage(ResultType.Error, "Error while running '{0}'.{1} See log for details.".format_with(chocoPowerShellScript, Environment.NewLine)));
                    }
                    packageResult.Messages.Add(new ResultMessage(ResultType.Note, "Ran '{0}'".format_with(chocoPowerShellScript)));
                }
            }

            return(installerRun);
        }
        public void remove(RegistryApplicationKey key, ChocolateyConfiguration config, PackageResult packageResult, string packageCacheLocation)
        {
            var userProvidedUninstallArguments = string.Empty;
            var userOverrideUninstallArguments = false;
            var package = packageResult.Package;

            if (package != null)
            {
                if (!PackageUtility.package_is_a_dependency(config, package.Id) || config.ApplyInstallArgumentsToDependencies)
                {
                    userProvidedUninstallArguments = config.InstallArguments;
                    userOverrideUninstallArguments = config.OverrideArguments;

                    if (!string.IsNullOrWhiteSpace(userProvidedUninstallArguments))
                    {
                        this.Log().Debug(ChocolateyLoggers.Verbose, " Using user passed {2}uninstaller args for {0}:'{1}'".format_with(package.Id, userProvidedUninstallArguments.escape_curly_braces(), userOverrideUninstallArguments ? "overriding " : string.Empty));
                    }
                }
            }

            //todo: #2562 if there is a local package, look to use it in the future
            if (string.IsNullOrWhiteSpace(key.UninstallString))
            {
                this.Log().Info(" Skipping auto uninstaller - '{0}' does not have an uninstall string.".format_with(!string.IsNullOrEmpty(key.DisplayName.to_string()) ? key.DisplayName.to_string().escape_curly_braces() : "The application"));
                return;
            }

            this.Log().Debug(() => " Preparing uninstall key '{0}' for '{1}'".format_with(key.UninstallString.to_string().escape_curly_braces(), key.DisplayName.to_string().escape_curly_braces()));

            if ((!string.IsNullOrWhiteSpace(key.InstallLocation) && !_fileSystem.directory_exists(key.InstallLocation.to_string().remove_surrounding_quotes())) || !_registryService.installer_value_exists(key.KeyPath, ApplicationParameters.RegistryValueInstallLocation))
            {
                this.Log().Info(" Skipping auto uninstaller - '{0}' appears to have been uninstalled already by other means.".format_with(!string.IsNullOrEmpty(key.DisplayName.to_string()) ? key.DisplayName.to_string().escape_curly_braces() : "The application"));
                this.Log().Debug(() => " Searched for install path '{0}' - found? {1}".format_with(key.InstallLocation.to_string().escape_curly_braces(), _fileSystem.directory_exists(key.InstallLocation)));
                this.Log().Debug(() => " Searched for registry key '{0}' value '{1}' - found? {2}".format_with(key.KeyPath.escape_curly_braces(), ApplicationParameters.RegistryValueInstallLocation, _registryService.installer_value_exists(key.KeyPath, ApplicationParameters.RegistryValueInstallLocation)));
                return;
            }

            // split on " /" and " -" for quite a bit more accuracy
            IList <string> uninstallArgsSplit = key.UninstallString.to_string().Replace("&quot;", "\"").Replace("&apos;", "'").Split(new[] { " /", " -" }, StringSplitOptions.RemoveEmptyEntries).ToList();
            var            uninstallExe       = uninstallArgsSplit.DefaultIfEmpty(string.Empty).FirstOrDefault().trim_safe();

            if (uninstallExe.Count(u => u == '"') > 2)
            {
                uninstallExe = uninstallExe.Split(new [] { " \"" }, StringSplitOptions.RemoveEmptyEntries).First();
            }

            if (uninstallExe.Count(u => u == ':') > 1)
            {
                try
                {
                    var firstMatch = Regex.Match(uninstallExe, @"\s+\w\:", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
                    uninstallExe = uninstallExe.Substring(0, firstMatch.Index);
                }
                catch (Exception ex)
                {
                    this.Log().Debug("Error splitting the uninstall string:{0} {1}".format_with(Environment.NewLine, ex.to_string()));
                }
            }
            var uninstallArgs = key.UninstallString.to_string().Replace("&quot;", "\"").Replace("&apos;", "'").Replace(uninstallExe.to_string(), string.Empty).trim_safe();

            uninstallExe = uninstallExe.remove_surrounding_quotes();
            this.Log().Debug(() => " Uninstaller path is '{0}'".format_with(uninstallExe));

            if (uninstallExe.contains("\\") || uninstallExe.contains("/"))
            {
                if (!_fileSystem.file_exists(uninstallExe))
                {
                    this.Log().Info(" Skipping auto uninstaller - The uninstaller file no longer exists. \"{0}\"".format_with(uninstallExe));
                    return;
                }
            }

            IInstaller installer = get_installer_type(key, uninstallExe, uninstallArgs);

            this.Log().Debug(() => " Installer type is '{0}'".format_with(installer.GetType().Name));

            if (key.InstallerType == InstallerType.Msi)
            {
                // because sometimes the key is set with /i to allow for modify :/
                uninstallArgs = uninstallArgs.Replace("/I{", "/X{");
                uninstallArgs = uninstallArgs.Replace("/i{", "/X{");
                uninstallArgs = uninstallArgs.Replace("/I ", "/X ");
                uninstallArgs = uninstallArgs.Replace("/i ", "/X ");
            }

            if (!key.HasQuietUninstall)
            {
                //todo: #2563 ultimately we should merge keys
                uninstallArgs += " " + installer.build_uninstall_command_arguments();
            }

            if (!string.IsNullOrWhiteSpace(userProvidedUninstallArguments))
            {
                if (userOverrideUninstallArguments)
                {
                    this.Log().Debug(() => " Replacing original uninstall arguments of '{0}' with '{1}'".format_with(uninstallArgs.escape_curly_braces(), userProvidedUninstallArguments.escape_curly_braces()));
                    uninstallArgs = userProvidedUninstallArguments;
                }
                else
                {
                    this.Log().Debug(() => " Appending original uninstall arguments with '{0}'".format_with(userProvidedUninstallArguments.escape_curly_braces()));
                    uninstallArgs += " " + userProvidedUninstallArguments;
                }
            }

            this.Log().Debug(() => " Setting up uninstall logging directory at {0}".format_with(packageCacheLocation.escape_curly_braces()));
            _fileSystem.create_directory_if_not_exists(_fileSystem.get_directory_name(packageCacheLocation));
            uninstallArgs = uninstallArgs.Replace(InstallTokens.PACKAGE_LOCATION, packageCacheLocation);
            uninstallArgs = uninstallArgs.Replace(InstallTokens.TEMP_LOCATION, packageCacheLocation);

            this.Log().Debug(() => " Args are '{0}'".format_with(uninstallArgs.escape_curly_braces()));

            if (!key.HasQuietUninstall && installer.GetType() == typeof(CustomInstaller))
            {
                if (!config.Information.IsLicensedVersion)
                {
                    this.Log().Warn(@"
  Did you know licensed versions of Chocolatey are 95% effective with 
   Automatic Uninstaller due to licensed enhancements and Package 
   Synchronizer?
");
                }

                var skipUninstaller = true;

                var timeout = config.PromptForConfirmation ? 0 : 30;

                var selection = InteractivePrompt.prompt_for_confirmation(
                    "Uninstall may not be silent (could not detect). Proceed?",
                    new[] { "yes", "no" },
                    defaultChoice: "no",
                    requireAnswer: true,
                    allowShortAnswer: true,
                    shortPrompt: true,
                    timeoutInSeconds: timeout
                    );
                if (selection.is_equal_to("yes"))
                {
                    skipUninstaller = false;
                }

                if (skipUninstaller)
                {
                    this.Log().Info(" Skipping auto uninstaller - Installer type was not detected and no silent uninstall key exists.");
                    this.Log().Warn("If the application was not removed with a chocolateyUninstall.ps1,{0} please remove it from Programs and Features manually.".format_with(Environment.NewLine));
                    return;
                }
            }

            var exitCode = _commandExecutor.execute(
                uninstallExe,
                uninstallArgs.trim_safe(),
                config.CommandExecutionTimeoutSeconds,
                (s, e) =>
            {
                if (e == null || string.IsNullOrWhiteSpace(e.Data))
                {
                    return;
                }
                this.Log().Info(() => " [AutoUninstaller] {0}".format_with(e.Data.escape_curly_braces()));
            },
                (s, e) =>
            {
                if (e == null || string.IsNullOrWhiteSpace(e.Data))
                {
                    return;
                }
                this.Log().Error(() => " [AutoUninstaller] {0}".format_with(e.Data.escape_curly_braces()));
            },
                updateProcessPath: false);

            if (!installer.ValidUninstallExitCodes.Contains(exitCode))
            {
                Environment.ExitCode = exitCode;
                string logMessage = " Auto uninstaller failed. Please remove machine installation manually.{0} Exit code was {1}".format_with(Environment.NewLine, exitCode);
                this.Log().Error(() => logMessage.escape_curly_braces());
                packageResult.Messages.Add(new ResultMessage(config.Features.FailOnAutoUninstaller ? ResultType.Error : ResultType.Warn, logMessage));
            }
            else
            {
                this.Log().Info(() => " Auto uninstaller has successfully uninstalled {0} or detected previous uninstall.".format_with(packageResult.Package.Id));
            }
        }
 public override void Because()
 {
     console.Setup(c => c.ReadLine()).Returns(""); //Enter pressed
     prompt = () => InteractivePrompt.prompt_for_confirmation(prompt_value, choices, default_choice, requireAnswer: false);
 }
 public override void Because()
 {
     prompt = () => InteractivePrompt.prompt_for_confirmation(prompt_value, choices, defaultChoice: null, requireAnswer: true, shortPrompt: true);
 }
 public override void Because()
 {
     prompt = () => InteractivePrompt.prompt_for_confirmation(prompt_value, choices, choices[0], requireAnswer: true);
 }
Ejemplo n.º 9
0
        public ConcurrentDictionary <string, PackageResult> uninstall_run(ChocolateyConfiguration config, Action <PackageResult> continueAction, bool performAction)
        {
            var packageUninstalls = new ConcurrentDictionary <string, PackageResult>();

            SemanticVersion version        = config.Version != null ? new SemanticVersion(config.Version) : null;
            var             packageManager = NugetCommon.GetPackageManager(config, _nugetLogger,
                                                                           installSuccessAction: null,
                                                                           uninstallSuccessAction: (e) =>
            {
                var pkg = e.Package;
                "chocolatey".Log().Info(ChocolateyLoggers.Important, " {0} has been successfully uninstalled.".format_with(pkg.Id));
            },
                                                                           addUninstallHandler: true);

            var loopCount = 0;

            packageManager.PackageUninstalling += (s, e) =>
            {
                var pkg = e.Package;

                // this section fires twice sometimes, like for older packages in a sxs install...
                var    results    = packageUninstalls.GetOrAdd(pkg.Id.to_lower() + "." + pkg.Version.to_string(), new PackageResult(pkg, e.InstallPath));
                string logMessage = "{0}{1} v{2}{3}".format_with(Environment.NewLine, pkg.Id, pkg.Version.to_string(), config.Force ? " (forced)" : string.Empty);
                if (results.Messages.Count((p) => p.Message == ApplicationParameters.Messages.NugetEventActionHeader) == 0)
                {
                    results.Messages.Add(new ResultMessage(ResultType.Debug, ApplicationParameters.Messages.NugetEventActionHeader));
                    "chocolatey".Log().Info(ChocolateyLoggers.Important, logMessage);
                    loopCount = 0;
                }
                else
                {
                    "chocolatey".Log().Debug(ChocolateyLoggers.Important, "Another time through!{0}{1}".format_with(Environment.NewLine, logMessage));
                    loopCount += 1;
                }

                if (loopCount == 10)
                {
                    this.Log().Warn("Loop detected. Attempting to break out. Check for issues with {0}".format_with(pkg.Id));
                    return;
                }

                // is this the latest version or have you passed --sxs? This is the only way you get through to the continue action.
                var latestVersion = packageManager.LocalRepository.FindPackage(e.Package.Id);
                if (latestVersion.Version == pkg.Version || config.AllowMultipleVersions)
                {
                    results.Messages.Add(new ResultMessage(ResultType.Debug, ApplicationParameters.Messages.ContinueChocolateyAction));
                    if (continueAction != null)
                    {
                        continueAction.Invoke(results);
                    }
                }
                else
                {
                    //todo:allow cleaning of pkgstore files
                }
            };

            set_package_names_if_all_is_specified(config, () =>
            {
                // force remove the item, ignore the dependencies
                // as those are going to be picked up anyway
                config.Force             = true;
                config.ForceDependencies = false;
            });

            foreach (string packageName in config.PackageNames.Split(new[] { ApplicationParameters.PackageNamesSeparator }, StringSplitOptions.RemoveEmptyEntries).or_empty_list_if_null())
            {
                remove_rollback_directory_if_exists(packageName);

                IList <IPackage> installedPackageVersions = new List <IPackage>();
                if (string.IsNullOrWhiteSpace(config.Version))
                {
                    installedPackageVersions = packageManager.LocalRepository.FindPackagesById(packageName).OrderBy((p) => p.Version).ToList();
                }
                else
                {
                    IPackage installedPackage = packageManager.LocalRepository.FindPackage(packageName);
                    if (installedPackage != null)
                    {
                        installedPackageVersions.Add(installedPackage);
                    }
                }

                if (installedPackageVersions.Count == 0)
                {
                    string logMessage = "{0} is not installed. Cannot uninstall a non-existent package.".format_with(packageName);
                    var    results    = packageUninstalls.GetOrAdd(packageName, new PackageResult(packageName, null, null));
                    results.Messages.Add(new ResultMessage(ResultType.Error, logMessage));

                    if (config.RegularOuptut)
                    {
                        this.Log().Error(ChocolateyLoggers.Important, logMessage);
                    }
                    continue;
                }

                var packageVersionsToRemove = installedPackageVersions.ToList();
                if (!config.AllVersions)
                {
                    if (config.PromptForConfirmation)
                    {
                        packageVersionsToRemove.Clear();

                        IList <string> choices     = new List <string>();
                        const string   abortChoice = "None";
                        choices.Add(abortChoice);
                        foreach (var installedVersion in installedPackageVersions.or_empty_list_if_null())
                        {
                            choices.Add(installedVersion.Version.to_string());
                        }

                        const string allVersionsChoice = "All versions";
                        if (installedPackageVersions.Count != 1)
                        {
                            choices.Add(allVersionsChoice);
                        }

                        var selection = InteractivePrompt.prompt_for_confirmation("Which version of {0} would you like to uninstall?".format_with(packageName), choices, abortChoice, true);

                        if (string.IsNullOrWhiteSpace(selection))
                        {
                            continue;
                        }
                        if (selection.is_equal_to(abortChoice))
                        {
                            continue;
                        }
                        if (selection.is_equal_to(allVersionsChoice))
                        {
                            packageVersionsToRemove = installedPackageVersions.ToList();
                            if (config.RegularOuptut)
                            {
                                this.Log().Info(() => "You selected to remove all versions of {0}".format_with(packageName));
                            }
                        }
                        else
                        {
                            IPackage pkg = installedPackageVersions.FirstOrDefault((p) => p.Version.to_string().is_equal_to(selection));
                            packageVersionsToRemove.Add(pkg);
                            if (config.RegularOuptut)
                            {
                                this.Log().Info(() => "You selected {0} v{1}".format_with(pkg.Id, pkg.Version.to_string()));
                            }
                        }
                    }
                }

                foreach (var packageVersion in packageVersionsToRemove)
                {
                    var pkgInfo = _packageInfoService.get_package_information(packageVersion);
                    if (pkgInfo != null && pkgInfo.IsPinned)
                    {
                        string logMessage    = "{0} is pinned. Skipping pinned package.".format_with(packageName);
                        var    pinnedResults = packageUninstalls.GetOrAdd(packageName, new PackageResult(packageName, null, null));
                        pinnedResults.Messages.Add(new ResultMessage(ResultType.Warn, logMessage));
                        pinnedResults.Messages.Add(new ResultMessage(ResultType.Inconclusive, logMessage));
                        if (config.RegularOuptut)
                        {
                            this.Log().Warn(ChocolateyLoggers.Important, logMessage);
                        }
                        continue;
                    }

                    if (performAction)
                    {
                        try
                        {
                            using (packageManager.SourceRepository.StartOperation(
                                       RepositoryOperationNames.Install,
                                       packageName,
                                       version == null ? null : version.ToString()))
                            {
                                rename_legacy_package_version(config, packageVersion, pkgInfo);
                                backup_existing_version(config, packageVersion);
                                packageManager.UninstallPackage(packageVersion, forceRemove: config.Force, removeDependencies: config.ForceDependencies);
                            }
                        }
                        catch (Exception ex)
                        {
                            var logMessage = "{0} not uninstalled. An error occurred during uninstall:{1} {2}".format_with(packageName, Environment.NewLine, ex.Message);
                            this.Log().Error(ChocolateyLoggers.Important, logMessage);
                            var result = packageUninstalls.GetOrAdd(packageVersion.Id.to_lower() + "." + packageVersion.Version.to_string(), new PackageResult(packageVersion, _fileSystem.combine_paths(ApplicationParameters.PackagesLocation, packageVersion.Id)));
                            result.Messages.Add(new ResultMessage(ResultType.Error, logMessage));
                            // do not call continueAction - will result in multiple passes
                        }
                    }
                    else
                    {
                        var result = packageUninstalls.GetOrAdd(packageVersion.Id.to_lower() + "." + packageVersion.Version.to_string(), new PackageResult(packageVersion, _fileSystem.combine_paths(ApplicationParameters.PackagesLocation, packageVersion.Id)));
                        if (continueAction != null)
                        {
                            continueAction.Invoke(result);
                        }
                    }
                }
            }

            return(packageUninstalls);
        }
Ejemplo n.º 10
0
        public bool run_action(ChocolateyConfiguration configuration, PackageResult packageResult, CommandNameType command)
        {
            var installerRun = false;

            var file = "chocolateyInstall.ps1";

            switch (command)
            {
            case CommandNameType.uninstall:
                file = "chocolateyUninstall.ps1";
                break;
            }

            var packageDirectory = packageResult.InstallLocation;

            if (packageDirectory.is_equal_to(ApplicationParameters.InstallLocation) || packageDirectory.is_equal_to(ApplicationParameters.PackagesLocation))
            {
                packageResult.Messages.Add(
                    new ResultMessage(
                        ResultType.Error,
                        "Install location is not specific enough, cannot run PowerShell script:{0} Erroneous install location captured as '{1}'".format_with(Environment.NewLine, packageResult.InstallLocation)
                        )
                    );

                return(false);
            }

            if (!_fileSystem.directory_exists(packageDirectory))
            {
                packageResult.Messages.Add(new ResultMessage(ResultType.Error, "Package install not found:'{0}'".format_with(packageDirectory)));
                return(installerRun);
            }

            var powershellScript = _fileSystem.get_files(packageDirectory, file, SearchOption.AllDirectories);

            if (powershellScript.Count() != 0)
            {
                var chocoPowerShellScript = powershellScript.FirstOrDefault();

                var failure = false;

                //todo: this is here for any possible compatibility issues. Should be reviewed and removed.
                ConfigurationBuilder.set_environment_variables(configuration);

                var package = packageResult.Package;
                Environment.SetEnvironmentVariable("chocolateyPackageName", package.Id);
                Environment.SetEnvironmentVariable("packageName", package.Id);
                Environment.SetEnvironmentVariable("chocolateyPackageVersion", package.Version.to_string());
                Environment.SetEnvironmentVariable("packageVersion", package.Version.to_string());
                Environment.SetEnvironmentVariable("chocolateyPackageFolder", packageDirectory);
                Environment.SetEnvironmentVariable("packageFolder", packageDirectory);
                Environment.SetEnvironmentVariable("installArguments", configuration.InstallArguments);
                Environment.SetEnvironmentVariable("installerArguments", configuration.InstallArguments);
                Environment.SetEnvironmentVariable("chocolateyInstallArguments", configuration.InstallArguments);
                Environment.SetEnvironmentVariable("packageParameters", configuration.PackageParameters);
                Environment.SetEnvironmentVariable("chocolateyPackageParameters", configuration.PackageParameters);
                if (configuration.ForceX86)
                {
                    Environment.SetEnvironmentVariable("chocolateyForceX86", "true");
                }
                if (configuration.OverrideArguments)
                {
                    Environment.SetEnvironmentVariable("chocolateyInstallOverride", "true");
                }

                if (configuration.NotSilent)
                {
                    Environment.SetEnvironmentVariable("chocolateyInstallOverride", "true");
                }

                //todo:if (configuration.NoOutput)
                //{
                //    Environment.SetEnvironmentVariable("ChocolateyEnvironmentQuiet","true");
                //}

                this.Log().Debug(ChocolateyLoggers.Important, "Contents of '{0}':".format_with(chocoPowerShellScript));
                string chocoPowerShellScriptContents = _fileSystem.read_file(chocoPowerShellScript);
                this.Log().Debug(chocoPowerShellScriptContents.escape_curly_braces());

                bool shouldRun = !configuration.PromptForConfirmation;

                if (!shouldRun)
                {
                    this.Log().Info(ChocolateyLoggers.Important, () => "The package {0} wants to run '{1}'.".format_with(package.Id, _fileSystem.get_file_name(chocoPowerShellScript)));
                    this.Log().Info(ChocolateyLoggers.Important, () => "Note: If you don't run this script, the installation will fail.");
                    this.Log().Info(ChocolateyLoggers.Important, () => @"Note: To confirm automatically next time, use '-y' or consider setting 
 'allowGlobalConfirmation'. Run 'choco feature -h' for more details.");

                    var selection = InteractivePrompt.prompt_for_confirmation(@"Do you want to run the script?", new[] { "yes", "no", "print" }, defaultChoice: null, requireAnswer: true);

                    if (selection.is_equal_to("print"))
                    {
                        this.Log().Info(ChocolateyLoggers.Important, "------ BEGIN SCRIPT ------");
                        this.Log().Info(() => "{0}{1}{0}".format_with(Environment.NewLine, chocoPowerShellScriptContents.escape_curly_braces()));
                        this.Log().Info(ChocolateyLoggers.Important, "------- END SCRIPT -------");
                        selection = InteractivePrompt.prompt_for_confirmation(@"Do you want to run this script?", new[] { "yes", "no" }, defaultChoice: null, requireAnswer: true);
                    }

                    if (selection.is_equal_to("yes"))
                    {
                        shouldRun = true;
                    }
                    if (selection.is_equal_to("no"))
                    {
                        Environment.ExitCode = 1;
                        packageResult.Messages.Add(new ResultMessage(ResultType.Error, "User cancelled powershell portion of installation for '{0}'.{1} Specify -n to skip automated script actions.".format_with(powershellScript.FirstOrDefault(), Environment.NewLine)));
                    }
                }

                if (shouldRun)
                {
                    installerRun = true;

                    if (configuration.Features.UsePowerShellHost)
                    {
                        add_assembly_resolver();
                    }

                    var result = new PowerShellExecutionResults
                    {
                        ExitCode = -1
                    };

                    try
                    {
                        result = configuration.Features.UsePowerShellHost
                                    ? Execute.with_timeout(configuration.CommandExecutionTimeoutSeconds).command(() => run_host(configuration, chocoPowerShellScript), result)
                                    : run_external_powershell(configuration, chocoPowerShellScript);
                    }
                    catch (Exception ex)
                    {
                        this.Log().Error(ex.Message);
                        result.ExitCode = -1;
                    }

                    if (configuration.Features.UsePowerShellHost)
                    {
                        remove_assembly_resolver();
                    }

                    if (result.StandardErrorWritten && configuration.Features.FailOnStandardError)
                    {
                        failure = true;
                    }
                    else if (result.StandardErrorWritten && result.ExitCode == 0)
                    {
                        this.Log().Warn(
                            () =>
                            @"Only an exit code of non-zero will fail the package by default. Set 
 `--failonstderr` if you want error messages to also fail a script. See 
 `choco -h` for details.");
                    }

                    if (result.ExitCode != 0)
                    {
                        failure = true;
                    }

                    if (failure)
                    {
                        Environment.ExitCode = result.ExitCode;
                        packageResult.Messages.Add(new ResultMessage(ResultType.Error, "Error while running '{0}'.{1} See log for details.".format_with(powershellScript.FirstOrDefault(), Environment.NewLine)));
                    }
                    packageResult.Messages.Add(new ResultMessage(ResultType.Note, "Ran '{0}'".format_with(chocoPowerShellScript)));
                }
            }

            return(installerRun);
        }
Ejemplo n.º 11
0
        public void run(PackageResult packageResult, ChocolateyConfiguration config)
        {
            if (!config.Features.AutoUninstaller)
            {
                this.Log().Info(" Skipping auto uninstaller - AutoUninstaller feature is not enabled.");
                return;
            }

            var pkgInfo = _packageInfoService.get_package_information(packageResult.Package);

            if (pkgInfo.RegistrySnapshot == null)
            {
                this.Log().Info(" Skipping auto uninstaller - No registry snapshot.");
                return;
            }

            var registryKeys = pkgInfo.RegistrySnapshot.RegistryKeys;

            if (registryKeys == null || registryKeys.Count == 0)
            {
                this.Log().Info(" Skipping auto uninstaller - No registry keys in snapshot.");
                return;
            }

            this.Log().Info(" Running auto uninstaller...");
            if (WaitForCleanup)
            {
                this.Log().Debug("Sleeping for {0} seconds to allow Windows to finish cleaning up.".format_with(SLEEP_TIME));
                Thread.Sleep((int)TimeSpan.FromSeconds(SLEEP_TIME).TotalMilliseconds);
            }

            foreach (var key in registryKeys.or_empty_list_if_null())
            {
                this.Log().Debug(() => " Preparing uninstall key '{0}'".format_with(key.UninstallString.escape_curly_braces()));

                if ((!string.IsNullOrWhiteSpace(key.InstallLocation) && !_fileSystem.directory_exists(key.InstallLocation)) || !_registryService.installer_value_exists(key.KeyPath, ApplicationParameters.RegistryValueInstallLocation))
                {
                    this.Log().Info(" Skipping auto uninstaller - The application appears to have been uninstalled already by other means.");
                    this.Log().Debug(() => " Searched for install path '{0}' - found? {1}".format_with(key.InstallLocation.escape_curly_braces(), _fileSystem.directory_exists(key.InstallLocation)));
                    this.Log().Debug(() => " Searched for registry key '{0}' value '{1}' - found? {2}".format_with(key.KeyPath.escape_curly_braces(), ApplicationParameters.RegistryValueInstallLocation, _registryService.installer_value_exists(key.KeyPath, ApplicationParameters.RegistryValueInstallLocation)));
                    continue;
                }

                // split on " /" and " -" for quite a bit more accuracy
                IList <string> uninstallArgsSplit = key.UninstallString.to_string().Split(new[] { " /", " -" }, StringSplitOptions.RemoveEmptyEntries).ToList();
                var            uninstallExe       = uninstallArgsSplit.DefaultIfEmpty(string.Empty).FirstOrDefault();
                var            uninstallArgs      = key.UninstallString.to_string().Replace(uninstallExe.to_string(), string.Empty);
                uninstallExe = uninstallExe.remove_surrounding_quotes();
                this.Log().Debug(() => " Uninstaller path is '{0}'".format_with(uninstallExe));


                IInstaller installer = new CustomInstaller();

                switch (key.InstallerType)
                {
                case InstallerType.Msi:
                    installer = new MsiInstaller();
                    break;

                case InstallerType.InnoSetup:
                    installer = new InnoSetupInstaller();
                    break;

                case InstallerType.Nsis:
                    installer = new NsisInstaller();
                    break;

                case InstallerType.InstallShield:
                    installer = new InstallShieldInstaller();
                    break;
                }

                this.Log().Debug(() => " Installer type is '{0}'".format_with(installer.GetType().Name));

                if (key.InstallerType == InstallerType.Msi)
                {
                    // because sometimes the key is set with /i to allow for modify :/
                    uninstallArgs = uninstallArgs.Replace("/I{", "/X{");
                    uninstallArgs = uninstallArgs.Replace("/i{", "/X{");
                    uninstallArgs = uninstallArgs.Replace("/I ", "/X ");
                    uninstallArgs = uninstallArgs.Replace("/i ", "/X ");
                }

                if (!key.HasQuietUninstall)
                {
                    //todo: ultimately we should merge keys
                    uninstallArgs += " " + installer.build_uninstall_command_arguments();
                }

                var logLocation = _fileSystem.combine_paths(_fileSystem.get_full_path(config.CacheLocation), "chocolatey", pkgInfo.Package.Id, pkgInfo.Package.Version.to_string());
                this.Log().Debug(() => " Setting up uninstall logging directory at {0}".format_with(logLocation.escape_curly_braces()));
                _fileSystem.create_directory_if_not_exists(_fileSystem.get_directory_name(logLocation));
                uninstallArgs = uninstallArgs.Replace(InstallTokens.PACKAGE_LOCATION, logLocation);

                this.Log().Debug(() => " Args are '{0}'".format_with(uninstallArgs.escape_curly_braces()));

                if (!key.HasQuietUninstall && installer.GetType() == typeof(CustomInstaller))
                {
                    var skipUninstaller = true;
                    if (config.PromptForConfirmation)
                    {
                        var selection = InteractivePrompt.prompt_for_confirmation("Uninstall may not be silent (could not detect). Proceed?", new[] { "yes", "no" }, defaultChoice: null, requireAnswer: true);
                        if (selection.is_equal_to("yes"))
                        {
                            skipUninstaller = false;
                        }
                    }

                    if (skipUninstaller)
                    {
                        this.Log().Info(" Skipping auto uninstaller - Installer type was not detected and no silent uninstall key exists.");
                        this.Log().Warn("If the application was not removed with a chocolateyUninstall.ps1,{0} please remove it from Programs and Features manually.".format_with(Environment.NewLine));
                        return;
                    }
                }

                var exitCode = _commandExecutor.execute(
                    uninstallExe,
                    uninstallArgs.trim_safe(),
                    config.CommandExecutionTimeoutSeconds,
                    (s, e) =>
                {
                    if (e == null || string.IsNullOrWhiteSpace(e.Data))
                    {
                        return;
                    }
                    this.Log().Info(() => " [AutoUninstaller] {0}".format_with(e.Data.escape_curly_braces()));
                },
                    (s, e) =>
                {
                    if (e == null || string.IsNullOrWhiteSpace(e.Data))
                    {
                        return;
                    }
                    this.Log().Error(() => " [AutoUninstaller] {0}".format_with(e.Data.escape_curly_braces()));
                },
                    updateProcessPath: false);

                if (!installer.ValidUninstallExitCodes.Contains(exitCode))
                {
                    Environment.ExitCode = exitCode;
                    string logMessage = " Auto uninstaller failed. Please remove machine installation manually.{0} Exit code was {1}".format_with(Environment.NewLine, exitCode);
                    this.Log().Error(() => logMessage.escape_curly_braces());
                    packageResult.Messages.Add(new ResultMessage(config.Features.FailOnAutoUninstaller ? ResultType.Error : ResultType.Warn, logMessage));
                }
                else
                {
                    this.Log().Info(() => " Auto uninstaller has successfully uninstalled {0} or detected previous uninstall.".format_with(packageResult.Package.Id));
                }
            }
        }
Ejemplo n.º 12
0
        public ConcurrentDictionary <string, PackageResult> uninstall_run(ChocolateyConfiguration config, Action <PackageResult> continueAction, bool performAction)
        {
            var packageUninstalls = new ConcurrentDictionary <string, PackageResult>();

            SemanticVersion version        = config.Version != null ? new SemanticVersion(config.Version) : null;
            var             packageManager = NugetCommon.GetPackageManager(config, _nugetLogger,
                                                                           installSuccessAction: null,
                                                                           uninstallSuccessAction: (e) =>
            {
                var pkg = e.Package;
                "chocolatey".Log().Info(ChocolateyLoggers.Important, " {0} has been successfully uninstalled.".format_with(pkg.Id));
            });

            packageManager.PackageUninstalling += (s, e) =>
            {
                var pkg = e.Package;

                // this section fires twice sometimes, like for older packages in a sxs install...
                var    results    = packageUninstalls.GetOrAdd(pkg.Id.to_lower() + "." + pkg.Version.to_string(), new PackageResult(pkg, e.InstallPath));
                string logMessage = "{0}{1} v{2}{3}".format_with(Environment.NewLine, pkg.Id, pkg.Version.to_string(), config.Force ? " (forced)" : string.Empty);
                if (results.Messages.Count((p) => p.Message == ApplicationParameters.Messages.NugetEventActionHeader) == 0)
                {
                    results.Messages.Add(new ResultMessage(ResultType.Debug, ApplicationParameters.Messages.NugetEventActionHeader));
                    "chocolatey".Log().Info(ChocolateyLoggers.Important, logMessage);
                }
                else
                {
                    "chocolatey".Log().Debug(ChocolateyLoggers.Important, "Another time through!{0}{1}".format_with(Environment.NewLine, logMessage));
                }

                // is this the latest version or have you passed --sxs? This is the only way you get through to the continue action.
                var latestVersion = packageManager.LocalRepository.FindPackage(e.Package.Id);
                if (latestVersion.Version == pkg.Version || config.AllowMultipleVersions)
                {
                    results.Messages.Add(new ResultMessage(ResultType.Debug, ApplicationParameters.Messages.ContinueChocolateyAction));
                    if (continueAction != null)
                    {
                        continueAction.Invoke(results);
                    }
                }
                else
                {
                    //todo:allow cleaning of pkgstore files
                }
            };

            set_package_names_if_all_is_specified(config, () =>
            {
                // force remove the item, ignore the dependencies
                // as those are going to be picked up anyway
                config.Force             = true;
                config.ForceDependencies = false;
            });

            foreach (string packageName in config.PackageNames.Split(new[] { ApplicationParameters.PackageNamesSeparator }, StringSplitOptions.RemoveEmptyEntries).or_empty_list_if_null())
            {
                if (packageName.to_lower().EndsWith(".config"))
                {
                    //todo: determine if .config file for packages .config
                    //todo: determine if config file exists
                }
                else
                {
                    IList <IPackage> installedPackageVersions = new List <IPackage>();
                    if (string.IsNullOrWhiteSpace(config.Version))
                    {
                        installedPackageVersions = packageManager.LocalRepository.FindPackagesById(packageName).OrderBy((p) => p.Version).ToList();
                    }
                    else
                    {
                        IPackage installedPackage = packageManager.LocalRepository.FindPackage(packageName);
                        if (installedPackage != null)
                        {
                            installedPackageVersions.Add(installedPackage);
                        }
                    }

                    if (installedPackageVersions.Count == 0)
                    {
                        string logMessage = "{0} is not installed. Cannot uninstall a non-existent package.".format_with(packageName);
                        var    results    = packageUninstalls.GetOrAdd(packageName, new PackageResult(packageName, null, null));
                        results.Messages.Add(new ResultMessage(ResultType.Error, logMessage));

                        if (config.RegularOuptut)
                        {
                            this.Log().Error(ChocolateyLoggers.Important, logMessage);
                        }
                        continue;
                    }

                    var packageVersionsToRemove = installedPackageVersions.ToList();
                    if (!config.AllVersions)
                    {
                        if (installedPackageVersions.Count != 1 && config.PromptForConfirmation)
                        {
                            packageVersionsToRemove.Clear();

                            IList <string> choices = new List <string>();
                            foreach (var installedVersion in installedPackageVersions.or_empty_list_if_null())
                            {
                                choices.Add(installedVersion.Version.to_string());
                            }
                            string allVersions = "All versions";
                            choices.Add(allVersions);
                            var selection = InteractivePrompt.prompt_for_confirmation("Which version of {0} would you like to uninstall?".format_with(packageName), choices, allVersions, false);

                            if (string.IsNullOrWhiteSpace(selection))
                            {
                                continue;
                            }
                            if (selection.is_equal_to(allVersions))
                            {
                                packageVersionsToRemove = installedPackageVersions.ToList();
                                if (config.RegularOuptut)
                                {
                                    this.Log().Info(() => "You selected to remove all versions of {0}".format_with(packageName));
                                }
                            }
                            else
                            {
                                IPackage pkg = installedPackageVersions.FirstOrDefault((p) => p.Version.to_string().is_equal_to(selection));
                                packageVersionsToRemove.Add(pkg);
                                if (config.RegularOuptut)
                                {
                                    this.Log().Info(() => "You selected {0} v{1}".format_with(pkg.Id, pkg.Version.to_string()));
                                }
                            }
                        }
                    }

                    foreach (var packageVersion in packageVersionsToRemove)
                    {
                        if (performAction)
                        {
                            using (packageManager.SourceRepository.StartOperation(
                                       RepositoryOperationNames.Install,
                                       packageName,
                                       version == null ? null : version.ToString()))
                            {
                                packageManager.UninstallPackage(packageVersion, forceRemove: config.Force, removeDependencies: config.ForceDependencies);
                            }
                        }
                        else
                        {
                            packageUninstalls.GetOrAdd(packageVersion.Id.to_lower() + "." + packageVersion.Version.to_string(), new PackageResult(packageVersion, ApplicationParameters.PackagesLocation));
                        }
                    }
                }
            }

            return(packageUninstalls);
        }