public VagrantService(ICommandExecutor commandExecutor, IFileSystem fileSystem, IConfigurationSettings configuration)
        {
            _commandExecutor = commandExecutor;
            _fileSystem = fileSystem;
            _configuration = configuration;

            var vagrantFound = false;
            var customVagrantPath = _configuration.PathToVagrant;
            if (!string.IsNullOrWhiteSpace(customVagrantPath))
            {
                if (!_fileSystem.file_exists(customVagrantPath))
                {
                    this.Log().Warn("Unable to find vagrant at the path specified. Using default instance.");
                }
                else
                {
                    this.Log().Warn("Using custom vagrant path at '{0}'.".format_with(customVagrantPath));
                    vagrantFound = true;
                    _vagrantExecutable = customVagrantPath;
                }
            }

            if (!vagrantFound)
            {
                _vagrantExecutable = @"C:\HashiCorp\Vagrant\bin\vagrant.exe";
                if (!_fileSystem.file_exists(_vagrantExecutable))
                {
                    _vagrantExecutable = _fileSystem.get_executable_path("vagrant.exe");
                }
            }

            //use_vagrant_directly();
        }
 /// <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));
     }
 }
Example #3
0
        public void delete_file(string folderName, string fileName)
        {
            if (String.IsNullOrWhiteSpace(folderName))
            {
                throw new ArgumentNullException("folderName");
            }
            if (String.IsNullOrWhiteSpace(fileName))
            {
                throw new ArgumentNullException("fileName");
            }

            var path = build_path(configuration.ImagesFolder, folderName, fileName);

            if (fileSystemSvc.file_exists(path))
            {
                fileSystemSvc.delete_file(path);
            }
        }
Example #4
0
        public PackageFiles read_from_file(string filePath)
        {
            if (!_fileSystem.file_exists(filePath))
            {
                return(null);
            }

            return(_xmlService.deserialize <PackageFiles>(filePath));
        }
        private void DetermineIfChocolateyExecutableIsBeingUsed()
        {
            var exePath = _fileSystem.combine_paths(ChocolateyInstall, "choco.exe");

            if (_fileSystem.file_exists(exePath))
            {
                IsChocolateyExecutableBeingUsed = true;
            }
        }
Example #6
0
        public Registry read_from_file(string filePath)
        {
            if (!_fileSystem.file_exists(filePath))
            {
                return(null);
            }

            return(_xmlService.deserialize <Registry>(filePath));
        }
        public static string get_powershell_location(IFileSystem fileSystem)
        {
            foreach (var powershellLocation in _powershellLocations)
            {
                if (fileSystem.file_exists(powershellLocation)) return powershellLocation;
            }

            var message = "Unable to find suitable location for PowerShell. Searched the following locations: '{0}'".format_with(string.Join("; ", _powershellLocations));
            "PowerShellExecutor".Log().Error(message);
            throw new FileNotFoundException(message);
        }
Example #8
0
        public static string get_powershell_location(IFileSystem fileSystem)
        {
            foreach (var powershellLocation in _powershellLocations)
            {
                if (fileSystem.file_exists(powershellLocation))
                {
                    return(powershellLocation);
                }
            }

            throw new FileNotFoundException("Unable to find suitable location for PowerShell. Searched the following locations: '{0}'".format_with(string.Join("; ", _powershellLocations)));
        }
Example #9
0
        public static string get_powershell_location(IFileSystem fileSystem)
        {
            foreach (var powershellLocation in _powershellLocations)
            {
                if (fileSystem.file_exists(powershellLocation))
                {
                    return powershellLocation;
                }
            }

            throw new FileNotFoundException("Unable to find suitable location for PowerShell. Searched the following locations: '{0}'".format_with(string.Join("; ", _powershellLocations)));
        }
Example #10
0
        public XmlType deserialize <XmlType>(string xmlFilePath)
        {
            return(FaultTolerance.try_catch_with_logging_exception(
                       () =>
            {
                var xmlSerializer = new XmlSerializer(typeof(XmlType));
                using (var fileStream = _fileSystem.open_file_readonly(xmlFilePath))
                    using (var fileReader = new StreamReader(fileStream))
                        using (var xmlReader = XmlReader.Create(fileReader))
                        {
                            if (!xmlSerializer.CanDeserialize(xmlReader))
                            {
                                this.Log().Warn("Cannot deserialize response of type {0}", typeof(XmlType));
                                return default(XmlType);
                            }

                            try
                            {
                                return (XmlType)xmlSerializer.Deserialize(xmlReader);
                            }
                            catch (InvalidOperationException ex)
                            {
                                // Check if its just a malformed document.
                                if (ex.Message.Contains("There is an error in XML document"))
                                {
                                    // If so, check for a backup file and try an parse that.
                                    if (_fileSystem.file_exists(xmlFilePath + ".backup"))
                                    {
                                        using (var backupStream = _fileSystem.open_file_readonly(xmlFilePath + ".backup"))
                                            using (var backupReader = new StreamReader(backupStream))
                                                using (var backupXmlReader = XmlReader.Create(backupReader))
                                                {
                                                    var validConfig = (XmlType)xmlSerializer.Deserialize(backupXmlReader);

                                                    // If there's no errors and it's valid, go ahead and replace the bad file with the backup.
                                                    if (validConfig != null)
                                                    {
                                                        _fileSystem.copy_file(xmlFilePath + ".backup", xmlFilePath, overwriteExisting: true);
                                                    }

                                                    return validConfig;
                                                }
                                    }
                                }

                                throw;
                            }
                        }
            },
                       "Error deserializing response of type {0}".format_with(typeof(XmlType)),
                       throwError: true));
        }
        public static void validate(IFileSystem fileSystem)
        {
            string licenseFile = ApplicationParameters.LicenseFileLocation;

            if (fileSystem.file_exists(licenseFile))
            {
                new LicenseValidator(PUBLIC_KEY, licenseFile).AssertValidLicense();
            }
            else
            {
                //free version
            }
        }
Example #12
0
        public static void validate(IFileSystem fileSystem)
        {
            string licenseFile = ApplicationParameters.LicenseFileLocation;

            if (fileSystem.file_exists(licenseFile))
            {
                new LicenseValidator(PUBLIC_KEY, licenseFile).AssertValidLicense();
            }
            else
            {
                //free version
            }
        }
        /// <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);
            }
        }
        /// <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);
            }
        }
 /// <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);
     }
 }
        private IEnumerable <ChocolateyConfiguration> get_packages_from_config(string packageConfigFile, ChocolateyConfiguration config, ConcurrentDictionary <string, PackageResult> packageInstalls)
        {
            IList <ChocolateyConfiguration> packageConfigs = new List <ChocolateyConfiguration>();

            if (!_fileSystem.file_exists(_fileSystem.get_full_path(packageConfigFile)))
            {
                var logMessage = "Could not find '{0}' in the location specified.".format_with(packageConfigFile);
                this.Log().Error(ChocolateyLoggers.Important, logMessage);
                var results = packageInstalls.GetOrAdd(packageConfigFile, new PackageResult(packageConfigFile, null, null));
                results.Messages.Add(new ResultMessage(ResultType.Error, logMessage));

                return(packageConfigs);
            }

            var settings = _xmlService.deserialize <PackagesConfigFileSettings>(_fileSystem.get_full_path(packageConfigFile));

            foreach (var pkgSettings in settings.Packages.or_empty_list_if_null())
            {
                if (!pkgSettings.Disabled)
                {
                    var packageConfig = config.deep_copy();
                    packageConfig.PackageNames      = pkgSettings.Id;
                    packageConfig.Sources           = string.IsNullOrWhiteSpace(pkgSettings.Source) ? packageConfig.Sources : pkgSettings.Source;
                    packageConfig.Version           = pkgSettings.Version;
                    packageConfig.InstallArguments  = string.IsNullOrWhiteSpace(pkgSettings.InstallArguments) ? packageConfig.InstallArguments : pkgSettings.InstallArguments;
                    packageConfig.PackageParameters = string.IsNullOrWhiteSpace(pkgSettings.PackageParameters) ? packageConfig.PackageParameters : pkgSettings.PackageParameters;
                    if (pkgSettings.ForceX86)
                    {
                        packageConfig.ForceX86 = true;
                    }
                    if (pkgSettings.AllowMultipleVersions)
                    {
                        packageConfig.AllowMultipleVersions = true;
                    }
                    if (pkgSettings.IgnoreDependencies)
                    {
                        packageConfig.IgnoreDependencies = true;
                    }

                    packageConfigs.Add(packageConfig);
                }
            }

            return(packageConfigs);
        }
Example #17
0
        /// <summary>
        ///   Looks for file and generates a notification.
        /// </summary>
        public void look_for_file_and_generate_notification()
        {
            try
            {
                IList <string> filesToProcess = new List <string>();

                if (is_directory(FilePath))
                {
                    filesToProcess = _fileSystem.get_files(FilePath, "*.*", SearchOption.AllDirectories).ToList();
                }
                else if (_fileSystem.file_exists(FilePath))
                {
                    filesToProcess.Add(FilePath);
                }

                if (filesToProcess.Count != 0)
                {
                    foreach (string file in filesToProcess)
                    {
                        var tempFile = file;
                        if (_renameFile)
                        {
                            var renamedFile = string.Format(
                                "{0}_renamed{1}",
                                _fileSystem.get_file_name_without_extension(file),
                                _fileSystem.get_file_extension(file));
                            tempFile = _fileSystem.combine_paths(_fileSystem.get_directory_name(file), renamedFile);
                            _fileSystem.move_file(file, tempFile);
                        }

                        file_found_event.Invoke(new FileFoundEventArgs(tempFile));
                    }
                }
            }
            catch (Exception ex)
            {
                this.Log()
                .Error(
                    () =>
                    string.Format("Exception caught when watching for trigger files:{0}{1}", Environment.NewLine, ex));
            }
        }
        public void set_executable_path_if_not_set()
        {
            if (!string.IsNullOrWhiteSpace(_exePath))
            {
                return;
            }

            foreach (var location in _exeLocations)
            {
                if (_fileSystem.file_exists(location))
                {
                    _exePath = location;
                    break;
                }
            }

            if (string.IsNullOrWhiteSpace(_exePath))
            {
                throw new FileNotFoundException("Unable to find suitable location for the executable. Searched the following locations: '{0}'".format_with(string.Join("; ", _exeLocations)));
            }
        }
Example #19
0
        public string hash_file(string filePath)
        {
            if (!_fileSystem.file_exists(filePath))
            {
                return(string.Empty);
            }

            try
            {
                var hash = _hashAlgorithm.ComputeHash(_fileSystem.read_file_bytes(filePath));

                return(BitConverter.ToString(hash).Replace("-", string.Empty));
            }
            catch (IOException ex)
            {
                this.Log().Warn(() => "Error computing hash for '{0}'{1} Captured error:{1}  {2}".format_with(filePath, Environment.NewLine, ex.Message));
                //IO.IO_FileTooLong2GB (over Int32.MaxValue)
                return(ApplicationParameters.HashProviderFileTooBig);

                return("UnableToDetectChanges_FileTooBig");
            }
        }
        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;
                }

                this.Log().Info(() => "Checking install.");
                var installResults = _testService.run(
                    "choco.exe install {0} --version {1} -fdvy --execution-timeout={2} --allow-downgrade".format_with(
                        message.PackageId,
                        message.PackageVersion,
                        _configuration.CommandExecutionTimeoutSeconds));

                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.");
                    uninstallResults = _testService.run("choco.exe uninstall {0} --version {1} -dvy --execution-timeout={2}".format_with(message.PackageId, message.PackageVersion, _configuration.CommandExecutionTimeoutSeconds));
                    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.");

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

                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);
            //}
        }
        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 #22
0
        public void run(ChocolateyConfiguration configuration)
        {
            var packageResults = _nugetService.get_all_installed_packages(configuration);
            var settings       = new XmlWriterSettings {
                Indent = true, Encoding = new UTF8Encoding(false)
            };

            FaultTolerance.try_catch_with_logging_exception(
                () =>
            {
                using (var stringWriter = new StringWriter())
                {
                    using (var xw = XmlWriter.Create(stringWriter, settings))
                    {
                        xw.WriteProcessingInstruction("xml", "version=\"1.0\" encoding=\"utf-8\"");
                        xw.WriteStartElement("packages");

                        foreach (var packageResult in packageResults)
                        {
                            xw.WriteStartElement("package");
                            xw.WriteAttributeString("id", packageResult.Package.Id);

                            if (configuration.ExportCommand.IncludeVersionNumbers)
                            {
                                xw.WriteAttributeString("version", packageResult.Package.Version.ToString());
                            }

                            xw.WriteEndElement();
                        }

                        xw.WriteEndElement();
                        xw.Flush();
                    }

                    var fullOutputFilePath = _fileSystem.get_full_path(configuration.ExportCommand.OutputFilePath);
                    var fileExists         = _fileSystem.file_exists(fullOutputFilePath);

                    // If the file doesn't already exist, just write the new one out directly
                    if (!fileExists)
                    {
                        _fileSystem.write_file(
                            fullOutputFilePath,
                            stringWriter.GetStringBuilder().ToString(),
                            new UTF8Encoding(false));

                        return;
                    }


                    // Otherwise, create an update file, and resiliently move it into place.
                    var tempUpdateFile = fullOutputFilePath + "." + Process.GetCurrentProcess().Id + ".update";
                    _fileSystem.write_file(tempUpdateFile,
                                           stringWriter.GetStringBuilder().ToString(),
                                           new UTF8Encoding(false));

                    _fileSystem.replace_file(tempUpdateFile, fullOutputFilePath, fullOutputFilePath + ".backup");
                }
            },
                errorMessage: "Error exporting currently installed packages",
                throwError: true
                );
        }
        public void run(PackageResult packageResult, ChocolateyConfiguration config)
        {
            var installDirectory = packageResult != null ? packageResult.InstallLocation : string.Empty;

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

            var transformFiles = _fileSystem.get_files(installDirectory, "*" + ApplicationParameters.ConfigFileTransformExtension, SearchOption.AllDirectories);

            foreach (var transformFile in transformFiles.or_empty_list_if_null())
            {
                this.Log().Debug(() => "Preparing transform for '{0}'".format_with(transformFile));
                var targetFileName = _fileSystem.get_file_name(transformFile.Replace(ApplicationParameters.ConfigFileTransformExtension, string.Empty));
                // target files must exist, otherwise one is added next to the transform
                var targetFiles = _fileSystem.get_files(installDirectory, targetFileName, SearchOption.AllDirectories);

                var targetFilesTest = targetFiles as IList <string> ?? targetFiles.ToList();
                if (!targetFilesTest.Any())
                {
                    targetFiles = new[] { transformFile.Replace(ApplicationParameters.ConfigFileTransformExtension, string.Empty) };
                    this.Log().Debug(() => "No matching files found for transform {0}.{1} Creating '{2}'".format_with(_fileSystem.get_file_name(transformFile), Environment.NewLine, targetFiles.FirstOrDefault()));
                }

                foreach (var targetFile in targetFilesTest.or_empty_list_if_null())
                {
                    GlobalMutex.enter(
                        () =>
                    {
                        var backupTargetFile = targetFile.Replace(ApplicationParameters.PackagesLocation, ApplicationParameters.PackageBackupLocation);

                        FaultTolerance.try_catch_with_logging_exception(
                            () =>
                        {
                            // if there is a backup, we need to put it back in place
                            // the user has indicated they are using transforms by putting
                            // the transform file into the folder, so we will override
                            // the replacement of the file and instead pull from the last
                            // backup and let the transform to its thing instead.
                            if (_fileSystem.file_exists(backupTargetFile))
                            {
                                this.Log().Debug(() => "Restoring backup configuration file for '{0}'.".format_with(targetFile));
                                _fileSystem.copy_file(backupTargetFile, targetFile, overwriteExisting: true);
                            }
                        },
                            "Error replacing backup config file",
                            throwError: false,
                            logWarningInsteadOfError: true);

                        try
                        {
                            this.Log().Info(() => "Transforming '{0}' with the data from '{1}'".format_with(_fileSystem.get_file_name(targetFile), _fileSystem.get_file_name(transformFile)));

                            using (var transformation = new XmlTransformation(_fileSystem.read_file(transformFile), isTransformAFile: false, logger: null))
                            {
                                using (var document = new XmlTransformableDocument {
                                    PreserveWhitespace = true
                                })
                                {
                                    using (var inputStream = _fileSystem.open_file_readonly(targetFile))
                                    {
                                        document.Load(inputStream);
                                    }

                                    // before applying the XDT transformation, let's make a
                                    // backup of the file that should be transformed, in case
                                    // things don't go correctly
                                    this.Log().Debug(() => "Creating backup configuration file for '{0}'.".format_with(targetFile));
                                    _fileSystem.copy_file(targetFile, backupTargetFile, overwriteExisting: true);

                                    bool succeeded = transformation.Apply(document);
                                    if (succeeded)
                                    {
                                        this.Log().Debug(() => "Transform applied successfully for '{0}'".format_with(targetFile));
                                        using (var memoryStream = new MemoryStream())
                                        {
                                            document.Save(memoryStream);
                                            memoryStream.Seek(0, SeekOrigin.Begin);
                                            using (var fileStream = _fileSystem.create_file(targetFile))
                                            {
                                                fileStream.SetLength(0);
                                                memoryStream.CopyTo(fileStream);
                                            }
                                        }

                                        // need to test that the transformed configuration file is valid
                                        // XML.  We can test this by trying to load it again into an XML document
                                        try
                                        {
                                            this.Log().Debug(() => "Verifying transformed configuration file...");
                                            document.Load(targetFile);
                                            this.Log().Debug(() => "Transformed configuration file verified.");
                                        }
                                        catch (Exception)
                                        {
                                            this.Log().Warn(() => "Transformed configuration file doesn't contain valid XML.  Restoring backup file...");
                                            _fileSystem.copy_file(backupTargetFile, targetFile, overwriteExisting: true);
                                            this.Log().Debug(() => "Backup file restored.");
                                        }
                                    }
                                    else
                                    {
                                        // at this point, there is no need to restore the backup file,
                                        // as the resulting transform hasn't actually been written to disk.
                                        this.Log().Warn(() => "Transform failed for '{0}'".format_with(targetFile));
                                    }
                                }
                            }
                        }
                        catch (Exception)
                        {
                            FaultTolerance.try_catch_with_logging_exception(
                                () =>
                            {
                                // something went wrong with the transformation, so we should restore
                                // the original configuration file from the backup
                                this.Log().Warn(() => "There was a problem transforming configuration file, restoring backup file...");
                                _fileSystem.copy_file(backupTargetFile, targetFile, overwriteExisting: true);
                                this.Log().Debug(() => "Backup file restored.");
                            },
                                "Error restoring backup configuration file.");
                        }
                    }, MUTEX_TIMEOUT);
                }
            }
        }
Example #24
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 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);
            //}
        }
        //// http://stackoverflow.com/a/8861895/18475
        //// http://stackoverflow.com/a/2864714/18475
        //[DllImport("kernel32.dll", SetLastError = true)]
        //private static extern bool SetDllDirectory(string lpPathName);

        //public struct DieInternal
        //{
        //    [SuppressUnmanagedCodeSecurity]
        //    [DllImport("diedll", CallingConvention = CallingConvention.StdCall, EntryPoint = "_DIE_scanExW@20", SetLastError = true)]
        //    internal static extern int scanExW_0([MarshalAs(UnmanagedType.LPWStr)] string pwszFileName, sbyte[] pszOutBuffer, int nOutBufferSize, uint nFlags, [MarshalAs(UnmanagedType.LPWStr)] string pwszDataBase);
        //}


        //public string scan_file(string filePath)
        //{
        //    if (Platform.get_platform() != PlatformType.Windows)
        //    {
        //        this.Log().Debug("Unable to detect file types when not on Windows");
        //        return string.Empty;
        //    }
        //    try
        //    {
        //        var successPath = SetDllDirectory(dieDllLocation);
        //        if (!successPath)
        //        {
        //            "chocolatey".Log().Warn("Error during native SetDllDirectory call - {0}".format_with(Marshal.GetLastWin32Error()));
        //        }
        //        var outputBuffer = new sbyte[1024];
        //        int outputBufferSize = outputBuffer.Length;
        //        const uint flags = DIE_SINGLELINEOUTPUT;

        //        var success = DieInternal.scanExW_0(filePath, outputBuffer, outputBufferSize, flags, databaseLocation);
        //        if (success != 0)
        //        {
        //            "chocolatey".Log().Warn("Error during native _DIE_scanExW call - {0}".format_with(Marshal.GetLastWin32Error()));
        //        }

        //        byte[] outputBytes = Array.ConvertAll(outputBuffer, (a) => (byte)a);

        //        var output = Encoding.UTF8.GetString(outputBytes).to_string().Trim('\0');

        //        return output;
        //    }
        //    catch (Exception ex)
        //    {
        //        this.Log().Warn("Unable to detect type for '{0}':{1} {2}".format_with(_fileSystem.get_file_name(filePath), Environment.NewLine, ex.Message));
        //        return string.Empty;
        //    }
        //}


        public string scan_file(string filePath)
        {
            if (Platform.get_platform() != PlatformType.Windows)
            {
                this.Log().Debug("Unable to detect file types when not on Windows");
                return(string.Empty);
            }

            // http://stackoverflow.com/q/5503951/18475
            // http://stackoverflow.com/a/10852827/18475
            // http://scottbilas.com/blog/automatically-choose-32-or-64-bit-mixed-mode-dlls/
            //todo: convert this to call the exe assembly instead. The dll is 32bit and won't work with AnyCPU

            filePath = _fileSystem.get_full_path(filePath);
            var dieDllLocation   = _fileSystem.combine_paths(ApplicationParameters.InstallLocation, "tools", "detector");
            var diecPath         = _fileSystem.combine_paths(ApplicationParameters.InstallLocation, "tools", "detector", "diec.exe");
            var databaseLocation = _fileSystem.get_full_path(_fileSystem.combine_paths(ApplicationParameters.InstallLocation, "tools", "detector", "db"));

            this.Log().Debug("Attempting to detect type for '{0}' with db '{1}'".format_with(_fileSystem.get_file_name(filePath), databaseLocation));

            if (!_fileSystem.directory_exists(diecPath) || !_fileSystem.directory_exists(databaseLocation))
            {
                var dieZipLocation = _fileSystem.combine_paths(ApplicationParameters.InstallLocation, "tools", "detector.zip");
                unzip_die_files(dieZipLocation, dieDllLocation);
                // finish unpacking
                Thread.Sleep(1000);
            }

            if (!_fileSystem.file_exists(filePath))
            {
                this.Log().Warn("File not found at '{0}'. Unable to detect type for inexistent file.".format_with(filePath));
                return(string.Empty);
            }

            try
            {
                //todo: detector databaselocation fails now - it's based on the current directory relative path
                //C:\\ProgramData\\chocolatey\\tools\\detector\\db
                var output = string.Empty;
                // var success = CommandExecutor.execute_static(diecPath, "\"{0}\" -singlelineoutput:yes -showoptions:no -showversion:no -database:\"{1}\"".format_with(filePath, databaseLocation),
                var success = CommandExecutor.execute_static(diecPath, "\"{0}\"".format_with(filePath),
                                                             60,
                                                             _fileSystem.get_current_directory(),
                                                             (s, e) =>
                {
                    if (!string.IsNullOrWhiteSpace(e.Data))
                    {
                        output = e.Data;
                    }
                },
                                                             (s, e) =>
                {
                    this.Log().Warn("{0}".format_with(e.Data));
                },
                                                             false,
                                                             false);

                return(output);
            }
            catch (Exception ex)
            {
                this.Log().Warn("Unable to detect type for '{0}':{1} {2}".format_with(_fileSystem.get_file_name(filePath), Environment.NewLine, ex.Message));
                return(string.Empty);
            }
        }
Example #27
0
        public XmlType deserialize <XmlType>(string xmlFilePath, int retryCount)
        {
            return(FaultTolerance.retry(retryCount, () => GlobalMutex.enter(
                                            () =>
            {
                this.Log().Trace("Entered mutex to deserialize '{0}'".format_with(xmlFilePath));

                return FaultTolerance.try_catch_with_logging_exception(
                    () =>
                {
                    var xmlSerializer = new XmlSerializer(typeof(XmlType));
                    using (var fileStream = _fileSystem.open_file_readonly(xmlFilePath))
                        using (var fileReader = new StreamReader(fileStream))
                            using (var xmlReader = XmlReader.Create(fileReader))
                            {
                                if (!xmlSerializer.CanDeserialize(xmlReader))
                                {
                                    this.Log().Warn("Cannot deserialize response of type {0}", typeof(XmlType));
                                    return default(XmlType);
                                }

                                try
                                {
                                    return (XmlType)xmlSerializer.Deserialize(xmlReader);
                                }
                                catch (InvalidOperationException ex)
                                {
                                    // Check if its just a malformed document.
                                    if (ex.Message.Contains("There is an error in XML document"))
                                    {
                                        // If so, check for a backup file and try an parse that.
                                        if (_fileSystem.file_exists(xmlFilePath + ".backup"))
                                        {
                                            using (var backupStream = _fileSystem.open_file_readonly(xmlFilePath + ".backup"))
                                                using (var backupReader = new StreamReader(backupStream))
                                                    using (var backupXmlReader = XmlReader.Create(backupReader))
                                                    {
                                                        var validConfig = (XmlType)xmlSerializer.Deserialize(backupXmlReader);

                                                        // If there's no errors and it's valid, go ahead and replace the bad file with the backup.
                                                        if (validConfig != null)
                                                        {
                                                            // Close fileReader so that we can copy the file without it being locked.
                                                            fileReader.Close();
                                                            _fileSystem.copy_file(xmlFilePath + ".backup", xmlFilePath, overwriteExisting: true);
                                                        }

                                                        return validConfig;
                                                    }
                                        }
                                    }

                                    throw;
                                }
                                finally
                                {
                                    foreach (var updateFile in _fileSystem.get_files(_fileSystem.get_directory_name(xmlFilePath), "*.update").or_empty_list_if_null())
                                    {
                                        this.Log().Debug("Removing '{0}'".format_with(updateFile));
                                        FaultTolerance.try_catch_with_logging_exception(
                                            () => _fileSystem.delete_file(updateFile),
                                            errorMessage: "Unable to remove update file",
                                            logDebugInsteadOfError: true,
                                            isSilent: true
                                            );
                                    }
                                }
                            }
                },
                    "Error deserializing response of type {0}".format_with(typeof(XmlType)),
                    throwError: true);
            }, MUTEX_TIMEOUT),
                                        waitDurationMilliseconds: 200,
                                        increaseRetryByMilliseconds: 200));
        }
Example #28
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));
            }
        }
Example #29
0
        public void run(PackageResult packageResult, ChocolateyConfiguration config)
        {
            var installDirectory = packageResult != null ? packageResult.InstallLocation : string.Empty;

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

            var transformFiles = _fileSystem.get_files(installDirectory, "*" + ApplicationParameters.ConfigFileTransformExtension, SearchOption.AllDirectories);

            foreach (var transformFile in transformFiles.or_empty_list_if_null())
            {
                this.Log().Debug(() => "Preparing transform for '{0}'".format_with(transformFile));
                var targetFileName = _fileSystem.get_file_name(transformFile.Replace(ApplicationParameters.ConfigFileTransformExtension, string.Empty));
                // target files must exist, otherwise one is added next to the transform
                var targetFiles = _fileSystem.get_files(installDirectory, targetFileName, SearchOption.AllDirectories);

                var targetFilesTest = targetFiles as IList <string> ?? targetFiles.ToList();
                if (!targetFilesTest.Any())
                {
                    targetFiles = new[] { transformFile.Replace(ApplicationParameters.ConfigFileTransformExtension, string.Empty) };
                    this.Log().Debug(() => "No matching files found for transform {0}.{1} Creating '{2}'".format_with(_fileSystem.get_file_name(transformFile), Environment.NewLine, targetFiles.FirstOrDefault()));
                }

                foreach (var targetFile in targetFilesTest.or_empty_list_if_null())
                {
                    FaultTolerance.try_catch_with_logging_exception(
                        () =>
                    {
                        // if there is a backup, we need to put it back in place
                        // the user has indicated they are using transforms by putting
                        // the transform file into the folder, so we will override
                        // the replacement of the file and instead pull from the last
                        // backup and let the transform to its thing instead.
                        var backupTargetFile = targetFile.Replace(ApplicationParameters.PackagesLocation, ApplicationParameters.PackageBackupLocation);
                        if (_fileSystem.file_exists(backupTargetFile))
                        {
                            this.Log().Debug(() => "Restoring backup configuration file for '{0}'.".format_with(targetFile));
                            _fileSystem.copy_file(backupTargetFile, targetFile, overwriteExisting: true);
                        }
                    },
                        "Error replacing backup config file",
                        throwError: false,
                        logWarningInsteadOfError: true);

                    FaultTolerance.try_catch_with_logging_exception(
                        () =>
                    {
                        this.Log().Info(() => "Transforming '{0}' with the data from '{1}'".format_with(_fileSystem.get_file_name(targetFile), _fileSystem.get_file_name(transformFile)));

                        using (var transformation = new XmlTransformation(_fileSystem.read_file(transformFile), isTransformAFile: false, logger: null))
                        {
                            using (var document = new XmlTransformableDocument {
                                PreserveWhitespace = true
                            })
                            {
                                using (var inputStream = _fileSystem.open_file_readonly(targetFile))
                                {
                                    document.Load(inputStream);
                                }

                                bool succeeded = transformation.Apply(document);
                                if (succeeded)
                                {
                                    this.Log().Debug(() => "Transform applied successfully for '{0}'".format_with(targetFile));
                                    using (var memoryStream = new MemoryStream())
                                    {
                                        document.Save(memoryStream);
                                        memoryStream.Seek(0, SeekOrigin.Begin);
                                        using (var fileStream = _fileSystem.create_file(targetFile))
                                        {
                                            memoryStream.CopyTo(fileStream);
                                        }
                                    }
                                }
                                else
                                {
                                    this.Log().Warn(() => "Transform failed for '{0}'".format_with(targetFile));
                                }
                            }
                        }
                    },
                        "Error transforming config file");
                }
            }
        }