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); }
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); }
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; }
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(""", "\"").Replace("'", "'").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(""", "\"").Replace("'", "'").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); }
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); }
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); }
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)); } } }
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); }