/// <summary>
 ///   Extract binary file from an assembly to a location on disk
 /// </summary>
 /// <param name="fileSystem">The file system.</param>
 /// <param name="assembly">The assembly.</param>
 /// <param name="manifestLocation">The manifest location.</param>
 /// <param name="filePath">The file path.</param>
 /// <param name="overwriteExisting">
 ///   if set to <c>true</c> [overwrite existing].
 /// </param>
 public static void extract_binary_file_from_assembly(IFileSystem fileSystem, IAssembly assembly, string manifestLocation, string filePath, bool overwriteExisting = false)
 {
     if (overwriteExisting || !fileSystem.file_exists(filePath))
     {
         fileSystem.create_directory_if_not_exists(fileSystem.get_directory_name(filePath));
         fileSystem.write_file(filePath, () => assembly.get_manifest_stream(manifestLocation));
     }
 }
        /// <summary>
        ///   Extract text file from assembly to location on disk.
        /// </summary>
        /// <param name="fileSystem">The file system.</param>
        /// <param name="assembly">The assembly.</param>
        /// <param name="manifestLocation">The manifest location.</param>
        /// <param name="filePath">The file path.</param>
        /// <param name="overwriteExisting">
        ///   if set to <c>true</c> [overwrite existing].
        /// </param>
        /// <exception cref="System.IO.FileNotFoundException"></exception>
        public static void extract_text_file_from_assembly(IFileSystem fileSystem, IAssembly assembly, string manifestLocation, string filePath, bool overwriteExisting = false)
        {
            if (overwriteExisting || !fileSystem.file_exists(filePath))
            {
                fileSystem.create_directory_if_not_exists(fileSystem.get_directory_name(filePath));
                var fileText = assembly.get_manifest_string(manifestLocation);
                if (string.IsNullOrWhiteSpace(fileText))
                {
                    string errorMessage = "Could not find a file in the manifest resource stream of '{0}' at '{1}'.".format_with(assembly.FullName, manifestLocation);
                    "chocolatey".Log().Error(() => errorMessage);
                    throw new FileNotFoundException(errorMessage);
                }

                fileSystem.write_file(filePath, fileText, Encoding.UTF8);
            }
        }
Example #3
0
 /// <summary>
 ///   Extract binary file from an assembly to a location on disk
 /// </summary>
 /// <param name="fileSystem">The file system.</param>
 /// <param name="assembly">The assembly.</param>
 /// <param name="manifestLocation">The manifest location.</param>
 /// <param name="filePath">The file path.</param>
 /// <param name="overwriteExisting">
 ///   if set to <c>true</c> [overwrite existing].
 /// </param>
 /// <param name="throwEror">Throw an error if there are issues</param>
 public static void extract_binary_file_from_assembly(IFileSystem fileSystem, IAssembly assembly, string manifestLocation, string filePath, bool overwriteExisting = false, bool throwEror = true)
 {
     if (overwriteExisting || !fileSystem.file_exists(filePath))
     {
         FaultTolerance.try_catch_with_logging_exception(
             () =>
         {
             fileSystem.create_directory_if_not_exists(fileSystem.get_directory_name(filePath));
             fileSystem.write_file(filePath, () => assembly.get_manifest_stream(manifestLocation));
         },
             errorMessage: "Unable to extract binary",
             throwError: throwEror,
             logWarningInsteadOfError: false,
             logDebugInsteadOfError: !throwEror,
             isSilent: !throwEror);
     }
 }
Example #4
0
        private static void set_file_configuration(ChocolateyConfiguration config, IFileSystem fileSystem, IXmlService xmlService, Action <string> notifyWarnLoggingAction)
        {
            var globalConfigPath = ApplicationParameters.GlobalConfigFileLocation;

            AssemblyFileExtractor.extract_text_file_from_assembly(fileSystem, Assembly.GetExecutingAssembly(), ApplicationParameters.ChocolateyConfigFileResource, globalConfigPath);

            var configFileSettings = xmlService.deserialize <ConfigFileSettings>(globalConfigPath);
            var sources            = new StringBuilder();

            foreach (var source in configFileSettings.Sources.Where(s => !s.Disabled).or_empty_list_if_null())
            {
                sources.AppendFormat("{0};", source.Value);
            }
            if (sources.Length != 0)
            {
                config.Sources = sources.Remove(sources.Length - 1, 1).ToString();
            }

            set_machine_sources(config, configFileSettings);

            config.CacheLocation = !string.IsNullOrWhiteSpace(configFileSettings.CacheLocation) ? configFileSettings.CacheLocation : System.Environment.GetEnvironmentVariable("TEMP");
            if (string.IsNullOrWhiteSpace(config.CacheLocation))
            {
                config.CacheLocation = fileSystem.combine_paths(ApplicationParameters.InstallLocation, "temp");
            }

            FaultTolerance.try_catch_with_logging_exception(
                () => fileSystem.create_directory_if_not_exists(config.CacheLocation),
                "Could not create temp directory at '{0}'".format_with(config.CacheLocation),
                logWarningInsteadOfError: true);

            config.ContainsLegacyPackageInstalls = configFileSettings.ContainsLegacyPackageInstalls;
            if (configFileSettings.CommandExecutionTimeoutSeconds <= 0)
            {
                configFileSettings.CommandExecutionTimeoutSeconds = ApplicationParameters.DefaultWaitForExitInSeconds;
            }
            config.CommandExecutionTimeoutSeconds = configFileSettings.CommandExecutionTimeoutSeconds;

            set_feature_flags(config, configFileSettings);

            // save so all updated configuration items get set to existing config
            FaultTolerance.try_catch_with_logging_exception(
                () => xmlService.serialize(configFileSettings, globalConfigPath),
                "Error updating '{0}'. Please ensure you have permissions to do so".format_with(globalConfigPath),
                logWarningInsteadOfError: true);
        }
        private void debug_gist(NewGist gist)
        {
            if (!_configuration.IsDebugMode)
            {
                return;
            }

            var gistFilesLocation = _fileSystem.combine_paths(_fileSystem.get_temp_path(), ApplicationParameters.Name, "Gist_" + DateTime.Now.ToString("yyyyMMdd_HHmmss_ffff"));

            this.Log().Info(() => "Generating gist files for gist '{0}' at '{1}'.".format_with(gist.Description.escape_curly_braces(), gistFilesLocation));
            _fileSystem.create_directory_if_not_exists(gistFilesLocation);
            _fileSystem.write_file(_fileSystem.combine_paths(gistFilesLocation, "description.txt"), gist.Description, Encoding.UTF8);

            foreach (var file in gist.Files)
            {
                _fileSystem.write_file(_fileSystem.combine_paths(gistFilesLocation, file.Key), file.Value, Encoding.UTF8);
            }
        }
Example #6
0
        private static void set_file_configuration(ChocolateyConfiguration config, IFileSystem fileSystem, IXmlService xmlService, Action <string> notifyWarnLoggingAction)
        {
            var globalConfigPath = ApplicationParameters.GlobalConfigFileLocation;

            AssemblyFileExtractor.extract_text_file_from_assembly(fileSystem, Assembly.GetExecutingAssembly(), ApplicationParameters.ChocolateyConfigFileResource, globalConfigPath);

            var configFileSettings = xmlService.deserialize <ConfigFileSettings>(globalConfigPath);
            var sources            = new StringBuilder();

            var defaultSourcesInOrder = configFileSettings.Sources.Where(s => !s.Disabled).or_empty_list_if_null().ToList();

            if (configFileSettings.Sources.Any(s => s.Priority > 0))
            {
                defaultSourcesInOrder = configFileSettings.Sources.Where(s => !s.Disabled && s.Priority != 0).OrderBy(s => s.Priority).or_empty_list_if_null().ToList();
                defaultSourcesInOrder.AddRange(configFileSettings.Sources.Where(s => !s.Disabled && s.Priority == 0).or_empty_list_if_null().ToList());
            }

            foreach (var source in defaultSourcesInOrder)
            {
                sources.AppendFormat("{0};", source.Value);
            }
            if (sources.Length != 0)
            {
                config.Sources = sources.Remove(sources.Length - 1, 1).ToString();
            }

            set_machine_sources(config, configFileSettings);

            set_config_items(config, configFileSettings, fileSystem);

            FaultTolerance.try_catch_with_logging_exception(
                () => fileSystem.create_directory_if_not_exists(config.CacheLocation),
                "Could not create temp directory at '{0}'".format_with(config.CacheLocation),
                logWarningInsteadOfError: true);

            set_feature_flags(config, configFileSettings);

            // save so all updated configuration items get set to existing config
            FaultTolerance.try_catch_with_logging_exception(
                () => xmlService.serialize(configFileSettings, globalConfigPath),
                "Error updating '{0}'. Please ensure you have permissions to do so".format_with(globalConfigPath),
                logWarningInsteadOfError: true);
        }
Example #7
0
        public void serialize <XmlType>(XmlType xmlType, string xmlFilePath)
        {
            _fileSystem.create_directory_if_not_exists(_fileSystem.get_directory_name(xmlFilePath));

            FaultTolerance.try_catch_with_logging_exception(
                () =>
            {
                var xmlSerializer = new XmlSerializer(typeof(XmlType));
                var textWriter    = new StreamWriter(xmlFilePath, append: false, encoding: Encoding.UTF8)
                {
                    AutoFlush = true
                };

                xmlSerializer.Serialize(textWriter, xmlType);
                textWriter.Flush();

                textWriter.Close();
                textWriter.Dispose();
            },
                "Error serializing type {0}".format_with(typeof(XmlType)),
                throwError: true);
        }
Example #8
0
        public void generate(ChocolateyConfiguration configuration)
        {
            var packageLocation = _fileSystem.combine_paths(_fileSystem.get_current_directory(), configuration.NewCommand.Name);

            if (_fileSystem.directory_exists(packageLocation) && !configuration.Force)
            {
                throw new ApplicationException("The location for the template already exists. You can:{0} 1. Remove '{1}'{0} 2. Use --force{0} 3. Specify a different name".format_with(Environment.NewLine, packageLocation));
            }

            if (configuration.RegularOutput)
            {
                this.Log().Info(() => "Creating a new package specification at {0}".format_with(packageLocation));
            }
            try
            {
                _fileSystem.delete_directory_if_exists(packageLocation, recursive: true);
            }
            catch (Exception ex)
            {
                if (configuration.RegularOutput)
                {
                    this.Log().Warn(() => "{0}".format_with(ex.Message));
                }
            }
            _fileSystem.create_directory_if_not_exists(packageLocation);
            var packageToolsLocation = _fileSystem.combine_paths(packageLocation, "tools");

            _fileSystem.create_directory_if_not_exists(packageToolsLocation);

            var tokens = new TemplateValues();

            if (configuration.NewCommand.AutomaticPackage)
            {
                tokens.set_auto();
            }

            // now override those values
            foreach (var property in configuration.NewCommand.TemplateProperties)
            {
                try
                {
                    tokens.GetType().GetProperty(property.Key, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase).SetValue(tokens, property.Value, null);
                    this.Log().Debug(() => "Set token for '{0}' to '{1}'".format_with(property.Key, property.Value));
                }
                catch (Exception)
                {
                    if (configuration.RegularOutput)
                    {
                        this.Log().Warn("Property {0} was not found for replacement in the Template Values.".format_with(property.Key));
                    }
                }
            }

            this.Log().Debug(() => "Token Values after merge:");
            foreach (var propertyInfo in tokens.GetType().GetProperties())
            {
                this.Log().Debug(() => " {0}={1}".format_with(propertyInfo.Name, propertyInfo.GetValue(tokens, null)));
            }

            generate_file_from_template(configuration, tokens, NuspecTemplate.Template, _fileSystem.combine_paths(packageLocation, "{0}.nuspec".format_with(tokens.PackageNameLower)), Encoding.UTF8);
            generate_file_from_template(configuration, tokens, ChocolateyInstallTemplate.Template, _fileSystem.combine_paths(packageToolsLocation, "chocolateyinstall.ps1"), Encoding.UTF8);
            generate_file_from_template(configuration, tokens, ChocolateyUninstallTemplate.Template, _fileSystem.combine_paths(packageToolsLocation, "chocolateyuninstall.ps1"), Encoding.UTF8);
            generate_file_from_template(configuration, tokens, ChocolateyReadMeTemplate.Template, _fileSystem.combine_paths(packageToolsLocation, "ReadMe.md"), Encoding.UTF8);

            this.Log().Info(ChocolateyLoggers.Important, "Successfully generated {0}{1} package specification files{2} at '{3}'".format_with(configuration.NewCommand.Name, configuration.NewCommand.AutomaticPackage ? " (automatic)" : string.Empty, Environment.NewLine, packageLocation));
        }
        public void remove(RegistryApplicationKey key, ChocolateyConfiguration config, PackageResult packageResult, string packageCacheLocation)
        {
            this.Log().Debug(() => " Preparing uninstall key '{0}'".format_with(key.UninstallString.to_string().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.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().Split(new[] { " /", " -" }, StringSplitOptions.RemoveEmptyEntries).ToList();
            var            uninstallExe       = uninstallArgsSplit.DefaultIfEmpty(string.Empty).FirstOrDefault();

            if (uninstallExe.Count(u => u == '"') > 2)
            {
                uninstallExe = uninstallExe.Split(new [] { " \"" }, StringSplitOptions.RemoveEmptyEntries).First();
            }
            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));

            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: ultimately we should merge keys
                uninstallArgs += " " + installer.build_uninstall_command_arguments();
            }

            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));
            }
        }
Example #10
0
        private static void set_file_configuration(ChocolateyConfiguration config, IFileSystem fileSystem, IXmlService xmlService, Action<string> notifyWarnLoggingAction)
        {
            var globalConfigPath = ApplicationParameters.GlobalConfigFileLocation;
            AssemblyFileExtractor.extract_text_file_from_assembly(fileSystem, Assembly.GetExecutingAssembly(), ApplicationParameters.ChocolateyConfigFileResource, globalConfigPath);

            var configFileSettings = xmlService.deserialize<ConfigFileSettings>(globalConfigPath);
            var sources = new StringBuilder();

            var defaultSourcesInOrder = configFileSettings.Sources.Where(s => !s.Disabled).or_empty_list_if_null().ToList();
            if (configFileSettings.Sources.Any(s => s.Priority > 0))
            {
                defaultSourcesInOrder = configFileSettings.Sources.Where(s => !s.Disabled && s.Priority != 0).OrderBy(s => s.Priority).or_empty_list_if_null().ToList();
                defaultSourcesInOrder.AddRange(configFileSettings.Sources.Where(s => !s.Disabled && s.Priority == 0 ).or_empty_list_if_null().ToList());
            }

            foreach (var source in defaultSourcesInOrder)
            {
                sources.AppendFormat("{0};", source.Value);
            }
            if (sources.Length != 0)
            {
                config.Sources = sources.Remove(sources.Length - 1, 1).ToString();
            }

            set_machine_sources(config, configFileSettings);

            set_config_items(config, configFileSettings, fileSystem);

            FaultTolerance.try_catch_with_logging_exception(
                () => fileSystem.create_directory_if_not_exists(config.CacheLocation),
                "Could not create temp directory at '{0}'".format_with(config.CacheLocation),
                logWarningInsteadOfError: true);

            set_feature_flags(config, configFileSettings);

            // save so all updated configuration items get set to existing config
            FaultTolerance.try_catch_with_logging_exception(
                () => xmlService.serialize(configFileSettings, globalConfigPath),
                "Error updating '{0}'. Please ensure you have permissions to do so".format_with(globalConfigPath),
                logWarningInsteadOfError: true);
        }
Example #11
0
        private static void set_file_configuration(ChocolateyConfiguration config, ConfigFileSettings configFileSettings, IFileSystem fileSystem, Action<string> notifyWarnLoggingAction)
        {
            var sources = new StringBuilder();

            var defaultSourcesInOrder = configFileSettings.Sources.Where(s => !s.Disabled).or_empty_list_if_null().ToList();
            if (configFileSettings.Sources.Any(s => s.Priority > 0))
            {
                defaultSourcesInOrder = configFileSettings.Sources.Where(s => !s.Disabled && s.Priority != 0).OrderBy(s => s.Priority).or_empty_list_if_null().ToList();
                defaultSourcesInOrder.AddRange(configFileSettings.Sources.Where(s => !s.Disabled && s.Priority == 0 ).or_empty_list_if_null().ToList());
            }

            foreach (var source in defaultSourcesInOrder)
            {
                sources.AppendFormat("{0};", source.Value);
            }
            if (sources.Length != 0)
            {
                config.Sources = sources.Remove(sources.Length - 1, 1).ToString();
            }

            set_machine_sources(config, configFileSettings);

            set_config_items(config, configFileSettings, fileSystem);

            FaultTolerance.try_catch_with_logging_exception(
                () => fileSystem.create_directory_if_not_exists(config.CacheLocation),
                "Could not create temp directory at '{0}'".format_with(config.CacheLocation),
                logWarningInsteadOfError: true);

            set_feature_flags(config, configFileSettings);
        }
        private void test_package(VerifyPackageMessage message)
        {
            //var lockTaken = TransactionLock.acquire(VAGRANT_LOCK_NAME, 7200);
            //if (!lockTaken)
            //{
            //    Bootstrap.handle_exception(new ApplicationException("Testing package {0} v{1} timed out waiting on transaction lock to open".format_with(message.PackageId, message.PackageVersion)));
            //    return;
            //}

            try
            {
                this.Log().Info(() => "========== {0} v{1} ==========".format_with(message.PackageId, message.PackageVersion));
                this.Log().Info(() => "Testing Package: {0} Version: {1}".format_with(message.PackageId, message.PackageVersion));

                _fileSystem.delete_file(".\\choco_logs\\chocolatey.log");
                var prepSuccess  = _testService.prep();
                var resetSuccess = _testService.reset();
                if (!prepSuccess || !resetSuccess)
                {
                    Bootstrap.handle_exception(new ApplicationException("Unable to test package due to testing service issues. See log for details"));
                    return;
                }

                if (_fileSystem.file_exists(_configuration.VboxIdPath))
                {
                    _vmId          = _fileSystem.read_file(_configuration.VboxIdPath);
                    _vmIdAvailable = !string.IsNullOrWhiteSpace(_vmId);
                }

                var tempFolder = Environment.GetEnvironmentVariable("TEMP");
                if (_vmIdAvailable && !tempFolder.EndsWith(_vmId))
                {
                    var runFolder = "{0}\\{1}".format_with(tempFolder, _vmId);
                    this.Log().Info(() => "Setting temp folder to: {0}".format_with(runFolder));

                    Environment.SetEnvironmentVariable("TEMP", runFolder);
                    _fileSystem.create_directory_if_not_exists(runFolder);
                }

                this.Log().Info(() => "Checking install.");

                const string imageDirectory = ".\\images";
                _fileSystem.create_directory_if_not_exists(imageDirectory);
                var installImage = string.Empty;

                var installResults = _testService.run(
                    "choco.exe install {0} --version {1} -fdvy --execution-timeout={2} --allow-downgrade".format_with(
                        message.PackageId,
                        message.PackageVersion,
                        _configuration.CommandExecutionTimeoutSeconds),
                    () =>
                {
                    this.Log().Info(() => "Timeout triggered.");
                    if (string.IsNullOrWhiteSpace(_vboxManageExe) || string.IsNullOrWhiteSpace(_configuration.VboxIdPath))
                    {
                        return;
                    }
                    if (!_vmIdAvailable)
                    {
                        return;
                    }

                    var imageLocation = _fileSystem.combine_paths(imageDirectory, _imageFormat.format_with(
                                                                      message.PackageId,
                                                                      message.PackageVersion,
                                                                      DateTime.Now.ToString(_dateTimeFormat),
                                                                      "install"
                                                                      ));

                    try
                    {
                        CommandExecutor.execute_static(_vboxManageExe,
                                                       "controlvm {" + _vmId + "} screenshotpng " + imageLocation,
                                                       30,
                                                       _fileSystem.get_directory_name(Assembly.GetExecutingAssembly().Location),
                                                       (o, e) =>
                        {
                            if (e == null || string.IsNullOrWhiteSpace(e.Data))
                            {
                                return;
                            }
                            this.Log().Debug(() => " [VboxManage] {0}".format_with(e.Data));
                        },
                                                       (o, e) =>
                        {
                            if (e == null || string.IsNullOrWhiteSpace(e.Data))
                            {
                                return;
                            }
                            this.Log().Warn(() => " [VboxManage][Error] {0}".format_with(e.Data));
                        },
                                                       null,
                                                       updateProcessPath: false,
                                                       allowUseWindow: false);

                        if (_fileSystem.file_exists(imageLocation))
                        {
                            installImage = _imageUploadService.upload_image(imageLocation);
                        }
                    }
                    catch (Exception ex)
                    {
                        this.Log().Warn("Image capture failed for {0}v{1}:{2} {3}".format_with(message.PackageId, message.PackageVersion, Environment.NewLine, ex.Message));
                    }
                });

                installResults.ImageLink = installImage;

                if (had_environment_errors(installResults))
                {
                    return;
                }

                this.Log().Debug(() => "Grabbing actual log file to include in report.");
                var installLog     = string.Empty;
                var installLogFile = ".\\choco_logs\\chocolatey.log";
                try
                {
                    if (_fileSystem.file_exists(installLogFile))
                    {
                        installLog = _fileSystem.read_file(installLogFile);
                        _fileSystem.delete_file(installLogFile);
                    }
                }
                catch (Exception ex)
                {
                    Bootstrap.handle_exception(new ApplicationException("Unable to read file '{0}':{1} {2}".format_with(installLogFile, Environment.NewLine, ex.ToString()), ex));
                }

                this.Log().Debug(() => "Grabbing results files (.registry/.files) to include in report.");
                var registrySnapshot     = string.Empty;
                var registrySnapshotFile = ".\\files\\{0}.{1}\\.registry".format_with(message.PackageId, message.PackageVersion);
                try
                {
                    if (_fileSystem.file_exists(registrySnapshotFile))
                    {
                        registrySnapshot = _fileSystem.read_file(registrySnapshotFile);
                    }
                }
                catch (Exception ex)
                {
                    Bootstrap.handle_exception(new ApplicationException("Unable to read file '{0}':{1} {2}".format_with(registrySnapshotFile, Environment.NewLine, ex.ToString()), ex));
                }

                var filesSnapshot     = string.Empty;
                var filesSnapshotFile = ".\\files\\{0}.{1}\\.files".format_with(message.PackageId, message.PackageVersion);
                try
                {
                    if (_fileSystem.file_exists(filesSnapshotFile))
                    {
                        filesSnapshot = _fileSystem.read_file(filesSnapshotFile);
                    }
                }
                catch (Exception ex)
                {
                    Bootstrap.handle_exception(new ApplicationException("Unable to read file '{0}':{1} {2}".format_with(filesSnapshotFile, Environment.NewLine, ex.ToString()), ex));
                }

                var success = installResults.Success && installResults.ExitCode == 0;
                this.Log().Info(() => "Install was '{0}'.".format_with(success ? "successful" : "not successful"));

                if (detect_vagrant_errors(installResults.Logs, message.PackageId, message.PackageVersion))
                {
                    return;
                }

                var upgradeResults = new TestCommandOutputResult();

                var uninstallLog     = string.Empty;
                var uninstallResults = new TestCommandOutputResult();
                if (success)
                {
                    this.Log().Info(() => "Now checking uninstall.");

                    var uninstallImage = string.Empty;

                    uninstallResults = _testService.run("choco.exe uninstall {0} --version {1} -dvy --execution-timeout={2}".format_with(message.PackageId, message.PackageVersion, _configuration.CommandExecutionTimeoutSeconds),
                                                        () =>
                    {
                        if (string.IsNullOrWhiteSpace(_vboxManageExe) || string.IsNullOrWhiteSpace(_configuration.VboxIdPath))
                        {
                            return;
                        }
                        if (!_fileSystem.file_exists(_configuration.VboxIdPath))
                        {
                            return;
                        }
                        if (!_vmIdAvailable)
                        {
                            return;
                        }

                        var imageLocation = _fileSystem.combine_paths(imageDirectory, _imageFormat.format_with(
                                                                          message.PackageId,
                                                                          message.PackageVersion,
                                                                          DateTime.Now.ToString(_dateTimeFormat),
                                                                          "uninstall"
                                                                          ));

                        try
                        {
                            CommandExecutor.execute_static(_vboxManageExe,
                                                           "controlvm {" + _vmId + "} screenshotpng " + imageLocation,
                                                           30,
                                                           _fileSystem.get_directory_name(Assembly.GetExecutingAssembly().Location),
                                                           (o, e) =>
                            {
                                if (e == null || string.IsNullOrWhiteSpace(e.Data))
                                {
                                    return;
                                }
                                this.Log().Debug(() => " [VboxManage] {0}".format_with(e.Data));
                            },
                                                           (o, e) =>
                            {
                                if (e == null || string.IsNullOrWhiteSpace(e.Data))
                                {
                                    return;
                                }
                                this.Log().Warn(() => " [VboxManage][Error] {0}".format_with(e.Data));
                            },
                                                           null,
                                                           updateProcessPath: false,
                                                           allowUseWindow: false);

                            if (_fileSystem.file_exists(imageLocation))
                            {
                                uninstallImage = _imageUploadService.upload_image(imageLocation);
                            }
                        }
                        catch (Exception ex)
                        {
                            this.Log().Warn("Image capture failed for {0}v{1}:{2} {3}".format_with(message.PackageId, message.PackageVersion, Environment.NewLine, ex.Message));
                        }
                    });
                    this.Log().Info(() => "Uninstall was '{0}'.".format_with(uninstallResults.ExitCode == 0 ? "successful" : "not successful"));
                    this.Log().Debug(() => "Grabbing actual log file to include in report.");

                    uninstallResults.ImageLink = uninstallImage;

                    var uninstallLogFile = ".\\choco_logs\\chocolatey.log";
                    try
                    {
                        if (_fileSystem.file_exists(uninstallLogFile))
                        {
                            uninstallLog = _fileSystem.read_file(uninstallLogFile);
                            _fileSystem.delete_file(uninstallLogFile);
                        }
                    }
                    catch (Exception ex)
                    {
                        Bootstrap.handle_exception(new ApplicationException("Unable to read file '{0}':{1} {2}".format_with(uninstallLogFile, Environment.NewLine, ex.ToString()), ex));
                    }

                    if (had_environment_errors(uninstallResults))
                    {
                        return;
                    }
                    if (detect_vagrant_errors(uninstallResults.Logs, message.PackageId, message.PackageVersion))
                    {
                        return;
                    }
                }

                foreach (var subDirectory in _fileSystem.get_directories(".\\files").or_empty_list_if_null())
                {
                    try
                    {
                        _fileSystem.delete_directory_if_exists(subDirectory, recursive: true);
                    }
                    catch (Exception ex)
                    {
                        Bootstrap.handle_exception(new ApplicationException("Unable to cleanup files directory (where .chocolatey files are put):{0} {1}".format_with(Environment.NewLine, ex.ToString()), ex));
                    }
                }

                var logs = new List <PackageTestLog>();

                var summary = new StringBuilder();
                summary.AppendFormat("{0} v{1} - {2} - Package Test Results", message.PackageId, message.PackageVersion, success ? "Passed" : "Failed");
                summary.AppendFormat("{0} * [{1}packages/{2}/{3}]({1}packages/{2}/{3})", Environment.NewLine, _configuration.PackagesUrl.ensure_trailing_slash(), message.PackageId, message.PackageVersion);
                summary.AppendFormat("{0} * Tested {1} +00:00", Environment.NewLine, DateTime.UtcNow.ToString("dd MMM yyyy HH:mm:ss"));
                summary.AppendFormat("{0} * Tested against {1} ({2})", Environment.NewLine, "win2012r2x64", "Windows Server 2012 R2 x64");
                summary.AppendFormat("{0} * Tested with the latest version of choco, possibly a beta version.", Environment.NewLine);
                summary.AppendFormat(
                    "{0} * Tested with {1} service v{2}{3}",
                    Environment.NewLine,
                    ApplicationParameters.Name,
                    ApplicationParameters.ProductVersion,
                    string.IsNullOrWhiteSpace(_configuration.InstanceName) ? string.Empty : " (Instance: {0})".format_with(_configuration.InstanceName)
                    );
                summary.AppendFormat(
                    "{0} * Install {1}.",
                    Environment.NewLine,
                    installResults.ExitCode == 0
                        ? "was successful"
                        : "failed. Note that the process may have hung, indicating a not completely silent install. This is usually seen when the last entry in the log is calling the install. This can also happen when a window pops up and needs to be closed to continue");
                if (!string.IsNullOrWhiteSpace(upgradeResults.Logs))
                {
                    summary.AppendFormat(
                        "{0} * Upgrade {1}.",
                        Environment.NewLine,
                        upgradeResults.ExitCode == 0
                            ? "was successful"
                            : "failed. Note that the process may have hung, indicating a not completely silent install. This is usually seen when the last entry in the log is calling the install. This can also happen when a window pops up and needs to be closed to continue");
                }
                if (!string.IsNullOrWhiteSpace(uninstallResults.Logs))
                {
                    summary.AppendFormat(
                        "{0} * Uninstall {1}.",
                        Environment.NewLine,
                        uninstallResults.ExitCode == 0
                            ? "was successful"
                            : "failed (allowed). Note that the process may have hung, indicating a not completely silent uninstall. This is usually seen when the last entry in the log is calling the uninstall. This can also happen when a window pops up and needs to be closed to continue");
                }

                logs.Add(new PackageTestLog("_Summary.md", summary.ToString()));
                if (!string.IsNullOrWhiteSpace(installResults.Logs))
                {
                    logs.Add(new PackageTestLog("Install.txt", string.IsNullOrWhiteSpace(installLog) ? installResults.Logs : installLog));
                }
                if (!string.IsNullOrWhiteSpace(installResults.ImageLink))
                {
                    logs.Add(new PackageTestLog("InstallImage.md", @"
This is the image that was taken when the install test failed:

![{0} v{1} install failure]({2})
".format_with(message.PackageId, message.PackageVersion, installResults.ImageLink)));
                }

                if (!string.IsNullOrWhiteSpace(registrySnapshot))
                {
                    logs.Add(new PackageTestLog("1.RegistrySnapshot.xml", registrySnapshot));
                }
                if (!string.IsNullOrWhiteSpace(filesSnapshot))
                {
                    logs.Add(new PackageTestLog("FilesSnapshot.xml", filesSnapshot));
                }
                if (!string.IsNullOrWhiteSpace(upgradeResults.Logs))
                {
                    logs.Add(new PackageTestLog("Upgrade.txt", upgradeResults.Logs));
                }
                if (!string.IsNullOrWhiteSpace(uninstallResults.Logs))
                {
                    logs.Add(new PackageTestLog("Uninstall.txt", string.IsNullOrWhiteSpace(uninstallLog) ? uninstallResults.Logs : uninstallLog));
                }
                if (!string.IsNullOrWhiteSpace(uninstallResults.ImageLink))
                {
                    logs.Add(new PackageTestLog("UninstallImage.md", @"
This is the image that was taken when the uninstall test failed:

![{0} v{1} uninstall failure]({2})
".format_with(message.PackageId, message.PackageVersion, uninstallResults.ImageLink)));
                }

                EventManager.publish(
                    new PackageTestResultMessage(
                        message.PackageId,
                        message.PackageVersion,
                        "Windows2012R2 x64",
                        "win2012r2x64",
                        DateTime.UtcNow,
                        logs,
                        success: success
                        ));
            }
            catch (Exception ex)
            {
                Bootstrap.handle_exception(ex);
            }
            //finally
            //{
            //    TransactionLock.release(VAGRANT_LOCK_NAME, lockTaken: true);
            //}
        }
Example #13
0
        public void install(ChocolateyConfiguration configuration, PackageResult packageResult)
        {
            _fileSystem.create_directory_if_not_exists(ApplicationParameters.ShimsLocation);

            if (packageResult.InstallLocation.is_equal_to(ApplicationParameters.InstallLocation) || packageResult.InstallLocation.is_equal_to(ApplicationParameters.PackagesLocation))
            {
                var logMessage = "Install location is not specific enough, cannot run shimgen:{0} Erroneous install location captured as '{1}'".format_with(Environment.NewLine, packageResult.InstallLocation);
                packageResult.Messages.Add(new ResultMessage(ResultType.Warn, logMessage));
                this.Log().Error(logMessage);
                return;
            }

            //gather all .exes in the folder
            var exeFiles = _fileSystem.get_files(packageResult.InstallLocation, pattern: "*.exe", option: SearchOption.AllDirectories);

            foreach (string file in exeFiles.or_empty_list_if_null())
            {
                if (_fileSystem.file_exists(file + ".ignore"))
                {
                    continue;
                }
                bool isGui = _fileSystem.file_exists(file + ".gui");
                //todo: v2 be able to determine gui automatically

                var args           = ExternalCommandArgsBuilder.build_arguments(configuration, _shimGenArguments);
                var shimLocation   = _fileSystem.combine_paths(ApplicationParameters.ShimsLocation, _fileSystem.get_file_name(file));
                var argsForPackage = args.Replace(PATH_TOKEN, file.Replace(ApplicationParameters.InstallLocation, "..\\")).Replace(OUTPUT_TOKEN, shimLocation).Replace(ICON_PATH_TOKEN, file);
                if (isGui)
                {
                    argsForPackage += " --gui";
                }

                var exitCode = _commandExecutor.execute(
                    _shimGenExePath, argsForPackage, configuration.CommandExecutionTimeoutSeconds,
                    (s, e) =>
                {
                    if (string.IsNullOrWhiteSpace(e.Data))
                    {
                        return;
                    }
                    this.Log().Debug(() => " [ShimGen] {0}".format_with(e.Data));
                },
                    (s, e) =>
                {
                    if (string.IsNullOrWhiteSpace(e.Data))
                    {
                        return;
                    }
                    this.Log().Error(() => " [ShimGen] {0}".format_with(e.Data));
                },
                    updateProcessPath: true
                    );

                if (exitCode != 0)
                {
                    Environment.ExitCode = exitCode;
                }
                else
                {
                    this.Log().Info(() => " ShimGen has successfully created a {0}shim for {1}".format_with(isGui ? "gui " : string.Empty, _fileSystem.get_file_name(file)));
                    this.Log().Debug(() => "  Created: {0}{1}  Targeting: {2}{1}  IsGui:{3}{1}".format_with(shimLocation, Environment.NewLine, file, isGui));
                }
            }
        }
        private static void set_file_configuration(ChocolateyConfiguration config, IFileSystem fileSystem, IXmlService xmlService, Action<string> notifyWarnLoggingAction)
        {
            var globalConfigPath = ApplicationParameters.GlobalConfigFileLocation;
            AssemblyFileExtractor.extract_text_file_from_assembly(fileSystem, Assembly.GetExecutingAssembly(), ApplicationParameters.ChocolateyConfigFileResource, globalConfigPath);

            var configFileSettings = xmlService.deserialize<ConfigFileSettings>(globalConfigPath);
            var sources = new StringBuilder();
            foreach (var source in configFileSettings.Sources.Where(s => !s.Disabled).or_empty_list_if_null())
            {
                sources.AppendFormat("{0};", source.Value);
            }
            if (sources.Length != 0)
            {
                config.Sources = sources.Remove(sources.Length - 1, 1).ToString();
            }

            set_machine_sources(config, configFileSettings);

            config.CacheLocation = !string.IsNullOrWhiteSpace(configFileSettings.CacheLocation) ? configFileSettings.CacheLocation : System.Environment.GetEnvironmentVariable("TEMP");
            if (string.IsNullOrWhiteSpace(config.CacheLocation))
            {
                config.CacheLocation = fileSystem.combine_paths(ApplicationParameters.InstallLocation, "temp");
            }

            FaultTolerance.try_catch_with_logging_exception(
                () => fileSystem.create_directory_if_not_exists(config.CacheLocation),
                "Could not create temp directory at '{0}'".format_with(config.CacheLocation),
                logWarningInsteadOfError: true);

            config.ContainsLegacyPackageInstalls = configFileSettings.ContainsLegacyPackageInstalls;
            if (configFileSettings.CommandExecutionTimeoutSeconds <= 0)
            {
                configFileSettings.CommandExecutionTimeoutSeconds = ApplicationParameters.DefaultWaitForExitInSeconds;
            }
            config.CommandExecutionTimeoutSeconds = configFileSettings.CommandExecutionTimeoutSeconds;

            set_feature_flags(config, configFileSettings);

            // save so all updated configuration items get set to existing config
            FaultTolerance.try_catch_with_logging_exception(
                () => xmlService.serialize(configFileSettings, globalConfigPath),
                "Error updating '{0}'. Please ensure you have permissions to do so".format_with(globalConfigPath),
                logWarningInsteadOfError: true);
        }
Example #15
0
        public void generate(ChocolateyConfiguration configuration)
        {
            var logger = ChocolateyLoggers.Normal;

            if (configuration.QuietOutput)
            {
                logger = ChocolateyLoggers.LogFileOnly;
            }

            var packageLocation = _fileSystem.combine_paths(configuration.OutputDirectory ?? _fileSystem.get_current_directory(), configuration.NewCommand.Name);

            if (_fileSystem.directory_exists(packageLocation) && !configuration.Force)
            {
                throw new ApplicationException(
                          "The location for the template already exists. You can:{0} 1. Remove '{1}'{0} 2. Use --force{0} 3. Specify a different name".format_with(Environment.NewLine, packageLocation));
            }

            if (configuration.RegularOutput)
            {
                this.Log().Info(logger, () => "Creating a new package specification at {0}".format_with(packageLocation));
            }
            try
            {
                _fileSystem.delete_directory_if_exists(packageLocation, recursive: true);
            }
            catch (Exception ex)
            {
                if (configuration.RegularOutput)
                {
                    this.Log().Warn(() => "{0}".format_with(ex.Message));
                }
            }
            _fileSystem.create_directory_if_not_exists(packageLocation);
            var packageToolsLocation = _fileSystem.combine_paths(packageLocation, "tools");

            _fileSystem.create_directory_if_not_exists(packageToolsLocation);

            var tokens = new TemplateValues();

            if (configuration.NewCommand.AutomaticPackage)
            {
                tokens.set_auto();
            }

            // now override those values
            foreach (var property in configuration.NewCommand.TemplateProperties)
            {
                try
                {
                    tokens.GetType().GetProperty(property.Key, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase).SetValue(tokens, property.Value, null);
                    this.Log().Debug(() => "Set token for '{0}' to '{1}'".format_with(property.Key, property.Value));
                }
                catch (Exception)
                {
                    if (configuration.RegularOutput)
                    {
                        this.Log().Debug("Property {0} will be added to additional properties.".format_with(property.Key));
                    }
                    tokens.AdditionalProperties.Add(property.Key, property.Value);
                }
            }

            this.Log().Debug(() => "Token Values after merge:");
            foreach (var propertyInfo in tokens.GetType().GetProperties())
            {
                this.Log().Debug(() => " {0}={1}".format_with(propertyInfo.Name, propertyInfo.GetValue(tokens, null)));
            }
            foreach (var additionalProperty in tokens.AdditionalProperties.or_empty_list_if_null())
            {
                this.Log().Debug(() => " {0}={1}".format_with(additionalProperty.Key, additionalProperty.Value));
            }

            var defaultTemplateOverride = _fileSystem.combine_paths(ApplicationParameters.TemplatesLocation, "default");

            if (string.IsNullOrWhiteSpace(configuration.NewCommand.TemplateName) && (!_fileSystem.directory_exists(defaultTemplateOverride) || configuration.NewCommand.UseOriginalTemplate))
            {
                generate_file_from_template(configuration, tokens, NuspecTemplate.Template, _fileSystem.combine_paths(packageLocation, "{0}.nuspec".format_with(tokens.PackageNameLower)), Encoding.UTF8);
                generate_file_from_template(configuration, tokens, ChocolateyInstallTemplate.Template, _fileSystem.combine_paths(packageToolsLocation, "chocolateyinstall.ps1"), Encoding.UTF8);
                generate_file_from_template(configuration, tokens, ChocolateyBeforeModifyTemplate.Template, _fileSystem.combine_paths(packageToolsLocation, "chocolateybeforemodify.ps1"), Encoding.UTF8);
                generate_file_from_template(configuration, tokens, ChocolateyUninstallTemplate.Template, _fileSystem.combine_paths(packageToolsLocation, "chocolateyuninstall.ps1"), Encoding.UTF8);
                generate_file_from_template(configuration, tokens, ChocolateyLicenseFileTemplate.Template, _fileSystem.combine_paths(packageToolsLocation, "LICENSE.txt"), Encoding.UTF8);
                generate_file_from_template(configuration, tokens, ChocolateyVerificationFileTemplate.Template, _fileSystem.combine_paths(packageToolsLocation, "VERIFICATION.txt"), Encoding.UTF8);
                generate_file_from_template(configuration, tokens, ChocolateyReadMeTemplate.Template, _fileSystem.combine_paths(packageLocation, "ReadMe.md"), Encoding.UTF8);
            }
            else
            {
                configuration.NewCommand.TemplateName = string.IsNullOrWhiteSpace(configuration.NewCommand.TemplateName) ? "default" : configuration.NewCommand.TemplateName;

                var templatePath = _fileSystem.combine_paths(ApplicationParameters.TemplatesLocation, configuration.NewCommand.TemplateName);
                if (!_fileSystem.directory_exists(templatePath))
                {
                    throw new ApplicationException("Unable to find path to requested template '{0}'. Path should be '{1}'".format_with(configuration.NewCommand.TemplateName, templatePath));
                }

                this.Log().Info(configuration.QuietOutput ? logger : ChocolateyLoggers.Important, "Generating package from custom template at '{0}'.".format_with(templatePath));
                foreach (var file in _fileSystem.get_files(templatePath, "*.*", SearchOption.AllDirectories))
                {
                    var packageFileLocation = file.Replace(templatePath, packageLocation);
                    if (_fileSystem.get_file_extension(packageFileLocation).is_equal_to(".nuspec"))
                    {
                        packageFileLocation = _fileSystem.combine_paths(packageLocation, "{0}.nuspec".format_with(tokens.PackageNameLower));
                    }
                    generate_file_from_template(configuration, tokens, _fileSystem.read_file(file), packageFileLocation, Encoding.UTF8);
                }
            }

            this.Log().Info(configuration.QuietOutput ? logger : ChocolateyLoggers.Important,
                            "Successfully generated {0}{1} package specification files{2} at '{3}'".format_with(
                                configuration.NewCommand.Name, configuration.NewCommand.AutomaticPackage ? " (automatic)" : string.Empty, Environment.NewLine, packageLocation));
        }
Example #16
0
        public void serialize <XmlType>(XmlType xmlType, string xmlFilePath, bool isSilent)
        {
            _fileSystem.create_directory_if_not_exists(_fileSystem.get_directory_name(xmlFilePath));

            FaultTolerance.retry(3, () => GlobalMutex.enter(
                                     () =>
            {
                this.Log().Trace("Entered mutex to serialize '{0}'".format_with(xmlFilePath));
                FaultTolerance.try_catch_with_logging_exception(
                    () =>
                {
                    var xmlSerializer = new XmlSerializer(typeof(XmlType));

                    this.Log().Trace("Opening memory stream for xml file creation.");
                    using (var memoryStream = new MemoryStream())
                        using (var streamWriter = new StreamWriter(memoryStream, encoding: new UTF8Encoding(encoderShouldEmitUTF8Identifier: true))
                        {
                            AutoFlush = true
                        }
                               ){
                            xmlSerializer.Serialize(streamWriter, xmlType);
                            streamWriter.Flush();

                            // Grab the hash of both files and compare them.
                            this.Log().Trace("Hashing original file at '{0}'".format_with(xmlFilePath));
                            var originalFileHash  = _hashProvider.hash_file(xmlFilePath);
                            memoryStream.Position = 0;
                            if (!originalFileHash.is_equal_to(_hashProvider.hash_stream(memoryStream)))
                            {
                                this.Log().Trace("The hashes were different.");
                                // If there wasn't a file there in the first place, just write the new one out directly.
                                if (string.IsNullOrEmpty(originalFileHash))
                                {
                                    this.Log().Debug("There was no original file at '{0}'".format_with(xmlFilePath));
                                    memoryStream.Position = 0;
                                    _fileSystem.write_file(xmlFilePath, () => memoryStream);

                                    this.Log().Trace("Closing xml memory stream.");
                                    memoryStream.Close();
                                    streamWriter.Close();

                                    return;
                                }

                                // Otherwise, create an update file, and resiliently move it into place.
                                var tempUpdateFile = xmlFilePath + "." + Process.GetCurrentProcess().Id + ".update";
                                this.Log().Trace("Creating a temp file at '{0}'".format_with(tempUpdateFile));
                                memoryStream.Position = 0;
                                this.Log().Trace("Writing file '{0}'".format_with(tempUpdateFile));
                                _fileSystem.write_file(tempUpdateFile, () => memoryStream);

                                memoryStream.Close();
                                streamWriter.Close();

                                this.Log().Trace("Replacing file '{0}' with '{1}'.".format_with(xmlFilePath, tempUpdateFile));
                                _fileSystem.replace_file(tempUpdateFile, xmlFilePath, xmlFilePath + ".backup");
                            }
                        }
                },
                    errorMessage: "Error serializing type {0}".format_with(typeof(XmlType)),
                    throwError: true,
                    isSilent: isSilent);
            }, MUTEX_TIMEOUT),
                                 waitDurationMilliseconds: 200,
                                 increaseRetryByMilliseconds: 200);
        }
        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));

                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());
                _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));

                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("no"))
                        {
                            skipUninstaller = false;
                        }
                    }

                    if (skipUninstaller)
                    {
                        this.Log().Info(" Skipping auto uninstaller - Installer type was not detected and no silent uninstall key exists.");
                        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));
                },
                    (s, e) =>
                {
                    if (e == null || string.IsNullOrWhiteSpace(e.Data))
                    {
                        return;
                    }
                    this.Log().Error(() => " [AutoUninstaller] {0}".format_with(e.Data));
                },
                    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);
                    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));
                }
            }
        }
Example #18
0
        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: 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)) || !_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: 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))
            {
                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));
            }
        }