Example #1
0
        public static GenericRegistryValue get_value(RegistryHiveType hive, string subKeyPath, string registryValue)
        {
            var hiveActual = (RegistryHive)Enum.Parse(typeof(RegistryHive), hive.to_string(), ignoreCase: true);
            IList <RegistryKey> keyLocations = new List <RegistryKey>();

            if (Environment.Is64BitOperatingSystem)
            {
                keyLocations.Add(RegistryKey.OpenBaseKey(hiveActual, RegistryView.Registry64));
            }

            keyLocations.Add(RegistryKey.OpenBaseKey(hiveActual, RegistryView.Registry32));

            GenericRegistryValue value = null;

            foreach (var topLevelRegistryKey in keyLocations)
            {
                using (topLevelRegistryKey)
                {
                    var key = topLevelRegistryKey.OpenSubKey(subKeyPath, RegistryKeyPermissionCheck.ReadSubTree, RegistryRights.ReadKey);
                    if (key != null)
                    {
                        value = FaultTolerance.try_catch_with_logging_exception(
                            () =>
                        {
                            if (key.GetValueNames().Contains(registryValue, StringComparer.InvariantCultureIgnoreCase))
                            {
                                return(new GenericRegistryValue
                                {
                                    Name = registryValue,
                                    ParentKeyName = key.Name,
                                    Type = (RegistryValueKindType)Enum.Parse(typeof(RegistryValueKindType), key.GetValueKind(registryValue).to_string(), ignoreCase: true),
                                    Value = key.GetValue(registryValue).to_string(),
                                });
                            }

                            return(null);
                        },
                            "Could not get registry value '{0}' from key '{1}'".format_with(registryValue, key.Name),
                            logWarningInsteadOfError: true);

                        if (value != null)
                        {
                            break;
                        }
                    }
                }
            }

            return(value);
        }
Example #2
0
        public Registry get_installer_keys()
        {
            var snapshot        = new Registry();
            var windowsIdentity = WindowsIdentity.GetCurrent();

            if (windowsIdentity != null)
            {
                snapshot.User = windowsIdentity.User.to_string();
            }

            IList <RegistryKey> keys = new List <RegistryKey>();

            if (Environment.Is64BitOperatingSystem)
            {
                add_key(keys, RegistryHive.CurrentUser, RegistryView.Registry64);
                add_key(keys, RegistryHive.LocalMachine, RegistryView.Registry64);
            }

            add_key(keys, RegistryHive.CurrentUser, RegistryView.Registry32);
            add_key(keys, RegistryHive.LocalMachine, RegistryView.Registry32);

            foreach (var registryKey in keys)
            {
                var uninstallKey = FaultTolerance.try_catch_with_logging_exception(
                    () => registryKey.OpenSubKey(UNINSTALLER_KEY_NAME, RegistryKeyPermissionCheck.ReadSubTree, RegistryRights.ReadKey),
                    "Could not open uninstall subkey for key '{0}'".format_with(registryKey.Name),
                    logWarningInsteadOfError: true);

                if (uninstallKey != null)
                {
                    //Console.WriteLine("Evaluating {0} of {1}".format_with(uninstallKey.View, uninstallKey.Name));
                    evaluate_keys(uninstallKey, snapshot);
                }
                registryKey.Close();
                registryKey.Dispose();
            }

            if (_logOutput)
            {
                Console.WriteLine("");
                Console.WriteLine("A total of {0} unrecognized apps".format_with(snapshot.RegistryKeys.Where((p) => p.InstallerType == InstallerType.Unknown && p.is_in_programs_and_features()).Count()));
                Console.WriteLine("");

                Console.WriteLine("");
                Console.WriteLine("A total of {0} of {1} are programs and features apps".format_with(snapshot.RegistryKeys.Where((p) => p.is_in_programs_and_features()).Count(), snapshot.RegistryKeys.Count));
                Console.WriteLine("");
            }

            return(snapshot);
        }
        public ChocolateyPackageInformation get_package_information(IPackage package)
        {
            var packageInformation = new ChocolateyPackageInformation(package);

            if (package == null)
            {
                this.Log().Debug("No package information as package is null.");
                return(packageInformation);
            }

            var pkgStorePath = _fileSystem.combine_paths(ApplicationParameters.ChocolateyPackageInfoStoreLocation, "{0}.{1}".format_with(package.Id, package.Version.to_string()));

            if (!_fileSystem.directory_exists(pkgStorePath))
            {
                return(packageInformation);
            }

            FaultTolerance.try_catch_with_logging_exception(
                () =>
            {
                packageInformation.RegistrySnapshot = _registryService.read_from_file(_fileSystem.combine_paths(pkgStorePath, REGISTRY_SNAPSHOT_FILE));
            },
                "Unable to read registry snapshot file for {0} (located at {1})".format_with(package.Id, _fileSystem.combine_paths(pkgStorePath, REGISTRY_SNAPSHOT_FILE)),
                throwError: false,
                logWarningInsteadOfError: true
                );

            FaultTolerance.try_catch_with_logging_exception(
                () =>
            {
                packageInformation.FilesSnapshot = _filesService.read_from_file(_fileSystem.combine_paths(pkgStorePath, FILES_SNAPSHOT_FILE));
            },
                "Unable to read files snapshot file",
                throwError: false,
                logWarningInsteadOfError: true
                );

            packageInformation.HasSilentUninstall = _fileSystem.file_exists(_fileSystem.combine_paths(pkgStorePath, SILENT_UNINSTALLER_FILE));
            packageInformation.IsSideBySide       = _fileSystem.file_exists(_fileSystem.combine_paths(pkgStorePath, SIDE_BY_SIDE_FILE));
            packageInformation.IsPinned           = _fileSystem.file_exists(_fileSystem.combine_paths(pkgStorePath, PIN_FILE));
            var argsFile = _fileSystem.combine_paths(pkgStorePath, ARGS_FILE);

            if (_fileSystem.file_exists(argsFile))
            {
                packageInformation.Arguments = _fileSystem.read_file(argsFile);
            }

            return(packageInformation);
        }
Example #4
0
        public void serialize <XmlType>(XmlType xmlType, string xmlFilePath, bool isSilent)
        {
            _fileSystem.create_directory_if_not_exists(_fileSystem.get_directory_name(xmlFilePath));

            FaultTolerance.try_catch_with_logging_exception(
                () =>
            {
                var xmlSerializer = new XmlSerializer(typeof(XmlType));

                // Write the updated file to memory
                using (var memoryStream = new MemoryStream())
                    using (var streamWriter = new StreamWriter(memoryStream, encoding: new UTF8Encoding(encoderShouldEmitUTF8Identifier: true)))
                    {
                        xmlSerializer.Serialize(streamWriter, xmlType);
                        streamWriter.Flush();

                        memoryStream.Position = 0;

                        // Grab the hash of both files and compare them.
                        var originalFileHash = _hashProvider.hash_file(xmlFilePath);
                        if (!originalFileHash.is_equal_to(_hashProvider.hash_stream(memoryStream)))
                        {
                            // If there wasn't a file there in the first place, just write the new one out directly.
                            if (string.IsNullOrEmpty(originalFileHash))
                            {
                                using (var updateFileStream = _fileSystem.create_file(xmlFilePath))
                                {
                                    memoryStream.Position = 0;
                                    memoryStream.CopyTo(updateFileStream);

                                    return;
                                }
                            }

                            // Otherwise, create an update file, and resiliently move it into place.
                            var tempUpdateFile = xmlFilePath + ".update";
                            using (var updateFileStream = _fileSystem.create_file(tempUpdateFile))
                            {
                                memoryStream.Position = 0;
                                memoryStream.CopyTo(updateFileStream);
                            }
                            _fileSystem.replace_file(tempUpdateFile, xmlFilePath, xmlFilePath + ".backup");
                        }
                    }
            },
                "Error serializing type {0}".format_with(typeof(XmlType)),
                throwError: true,
                isSilent: isSilent);
        }
Example #5
0
 private static void remove_old_chocolatey_exe(IFileSystem fileSystem)
 {
     FaultTolerance.try_catch_with_logging_exception(
         () =>
     {
         fileSystem.delete_file(fileSystem.get_current_assembly_path() + ".old");
         fileSystem.delete_file(fileSystem.combine_paths(AppDomain.CurrentDomain.BaseDirectory, "choco.exe.old"));
     },
         errorMessage: "Attempting to delete choco.exe.old ran into an issue",
         throwError: false,
         logWarningInsteadOfError: true,
         logDebugInsteadOfError: false,
         isSilent: true
         );
 }
 /// <summary>
 ///   Extract binary file from an assembly to a location on disk
 /// </summary>
 /// <param name="fileSystem">The file system.</param>
 /// <param name="assembly">The assembly.</param>
 /// <param name="manifestLocation">The manifest location.</param>
 /// <param name="filePath">The file path.</param>
 /// <param name="overwriteExisting">
 ///   if set to <c>true</c> [overwrite existing].
 /// </param>
 /// <param name="throwEror">Throw an error if there are issues</param>
 public static void extract_binary_file_from_assembly(IFileSystem fileSystem, IAssembly assembly, string manifestLocation, string filePath, bool overwriteExisting = false, bool throwEror = true)
 {
     if (overwriteExisting || !fileSystem.file_exists(filePath))
     {
         FaultTolerance.try_catch_with_logging_exception(
             () =>
         {
             fileSystem.create_directory_if_not_exists(fileSystem.get_directory_name(filePath));
             fileSystem.write_file(filePath, () => assembly.get_manifest_stream(manifestLocation));
         },
             errorMessage: "Unable to extract binary",
             throwError: throwEror,
             logWarningInsteadOfError: false,
             logDebugInsteadOfError: !throwEror,
             isSilent: !throwEror);
     }
 }
Example #7
0
        private static void set_file_configuration(ChocolateyConfiguration config, IFileSystem fileSystem, IXmlService xmlService, Action <string> notifyWarnLoggingAction)
        {
            var globalConfigPath = ApplicationParameters.GlobalConfigFileLocation;

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

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

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

            set_machine_sources(config, configFileSettings);

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

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

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

            set_feature_flags(config, configFileSettings);

            // save so all updated configuration items get set to existing config
            FaultTolerance.try_catch_with_logging_exception(
                () => xmlService.serialize(configFileSettings, globalConfigPath),
                "Error updating '{0}'. Please ensure you have permissions to do so".format_with(globalConfigPath),
                logWarningInsteadOfError: true);
        }
        private void ensure_bad_package_path_is_clean(ChocolateyConfiguration config, PackageResult packageResult)
        {
            if (packageResult.InstallLocation == null)
            {
                return;
            }

            FaultTolerance.try_catch_with_logging_exception(
                () =>
            {
                string badPackageInstallPath = packageResult.InstallLocation.Replace(ApplicationParameters.PackagesLocation, ApplicationParameters.PackageFailuresLocation);
                if (_fileSystem.directory_exists(badPackageInstallPath))
                {
                    _fileSystem.delete_directory(badPackageInstallPath, recursive: true);
                }
            },
                "Attempted to delete bad package install path if existing. Had an error");
        }
Example #9
0
        public XmlType deserialize <XmlType>(string xmlFilePath)
        {
            return(FaultTolerance.try_catch_with_logging_exception(
                       () =>
            {
                var xmlSerializer = new XmlSerializer(typeof(XmlType));
                var xmlReader = XmlReader.Create(new StringReader(_fileSystem.read_file(xmlFilePath)));
                if (!xmlSerializer.CanDeserialize(xmlReader))
                {
                    this.Log().Warn("Cannot deserialize response of type {0}", typeof(XmlType));
                    return default(XmlType);
                }

                return (XmlType)xmlSerializer.Deserialize(xmlReader);
            },
                       "Error deserializing response of type {0}".format_with(typeof(XmlType)),
                       throwError: true));
        }
Example #10
0
        private static void set_file_configuration(ChocolateyConfiguration config, IFileSystem fileSystem, IXmlService xmlService, Action <string> notifyWarnLoggingAction)
        {
            var globalConfigPath = ApplicationParameters.GlobalConfigFileLocation;

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

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

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

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

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

            set_machine_sources(config, configFileSettings);

            set_config_items(config, configFileSettings, fileSystem);

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

            set_feature_flags(config, configFileSettings);

            // save so all updated configuration items get set to existing config
            FaultTolerance.try_catch_with_logging_exception(
                () => xmlService.serialize(configFileSettings, globalConfigPath),
                "Error updating '{0}'. Please ensure you have permissions to do so".format_with(globalConfigPath),
                logWarningInsteadOfError: true);
        }
Example #11
0
        public void rename_legacy_package_version(ChocolateyConfiguration config, IPackage installedPackage, ChocolateyPackageInformation pkgInfo)
        {
            if (pkgInfo != null && pkgInfo.IsSideBySide)
            {
                return;
            }

            var installDirectory = _fileSystem.combine_paths(ApplicationParameters.PackagesLocation, installedPackage.Id);

            if (!_fileSystem.directory_exists(installDirectory))
            {
                // if the folder has a version on it, we need to rename the folder first.
                var pathResolver = new ChocolateyPackagePathResolver(NugetCommon.GetNuGetFileSystem(config, _nugetLogger), useSideBySidePaths: true);
                installDirectory = pathResolver.GetInstallPath(installedPackage);
                if (_fileSystem.directory_exists(installDirectory))
                {
                    FaultTolerance.try_catch_with_logging_exception(
                        () => _fileSystem.move_directory(installDirectory, _fileSystem.combine_paths(ApplicationParameters.PackagesLocation, installedPackage.Id)),
                        "Error during old package rename");
                }
            }
        }
Example #12
0
        public void serialize <XmlType>(XmlType xmlType, string xmlFilePath)
        {
            _fileSystem.create_directory_if_not_exists(_fileSystem.get_directory_name(xmlFilePath));

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

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

                textWriter.Close();
                textWriter.Dispose();
            },
                "Error serializing type {0}".format_with(typeof(XmlType)),
                throwError: true);
        }
Example #13
0
        public void remove_rollback_directory_if_exists(string packageName)
        {
            var rollbackDirectory = _fileSystem.combine_paths(ApplicationParameters.PackageBackupLocation, packageName);

            if (!_fileSystem.directory_exists(rollbackDirectory))
            {
                //search for folder
                var possibleRollbacks = _fileSystem.get_directories(ApplicationParameters.PackageBackupLocation, packageName + "*");
                if (possibleRollbacks != null && possibleRollbacks.Count() != 0)
                {
                    rollbackDirectory = possibleRollbacks.OrderByDescending(p => p).DefaultIfEmpty(string.Empty).FirstOrDefault();
                }
            }

            if (string.IsNullOrWhiteSpace(rollbackDirectory) || !_fileSystem.directory_exists(rollbackDirectory))
            {
                return;
            }

            FaultTolerance.try_catch_with_logging_exception(
                () => _fileSystem.delete_directory_if_exists(rollbackDirectory, recursive: true),
                "Attempted to remove '{0}' but had an error:".format_with(rollbackDirectory),
                logWarningInsteadOfError: true);
        }
        private void get_values(RegistryKey key, string subKeyName, IList <GenericRegistryValue> values, bool expandValues)
        {
            if (key != null)
            {
                var subKey = FaultTolerance.try_catch_with_logging_exception(
                    () => key.OpenSubKey(subKeyName, RegistryKeyPermissionCheck.ReadSubTree, RegistryRights.ReadKey),
                    "Could not open uninstall subkey for key '{0}'".format_with(key.Name),
                    logWarningInsteadOfError: true);

                if (subKey != null)
                {
                    foreach (var valueName in subKey.GetValueNames())
                    {
                        values.Add(new GenericRegistryValue
                        {
                            Name          = valueName,
                            ParentKeyName = subKey.Name,
                            Type          = (RegistryValueKindType)Enum.Parse(typeof(RegistryValueKindType), subKey.GetValueKind(valueName).to_string(), ignoreCase: true),
                            Value         = subKey.GetValue(valueName, expandValues ? RegistryValueOptions.None : RegistryValueOptions.DoNotExpandEnvironmentNames).to_string().Replace("\0", string.Empty),
                        });
                    }
                }
            }
        }
        private void handle_extension_packages(ChocolateyConfiguration config, PackageResult packageResult)
        {
            if (packageResult == null)
            {
                return;
            }
            _fileSystem.create_directory_if_not_exists(ApplicationParameters.ExtensionsLocation);

            if (!packageResult.Name.to_lower().EndsWith(".extension"))
            {
                return;
            }

            var pkgExtensions = _fileSystem.combine_paths(ApplicationParameters.ExtensionsLocation, packageResult.Name);

            FaultTolerance.try_catch_with_logging_exception(
                () => _fileSystem.delete_directory_if_exists(pkgExtensions, recursive: true),
                "Attempted to remove '{0}' but had an error".format_with(pkgExtensions));

            if (!config.CommandName.is_equal_to(CommandNameType.uninstall.to_string()))
            {
                if (packageResult.InstallLocation == null)
                {
                    return;
                }

                _fileSystem.create_directory_if_not_exists(pkgExtensions);
                FaultTolerance.try_catch_with_logging_exception(
                    () => _fileSystem.copy_directory(packageResult.InstallLocation, pkgExtensions, overwriteExisting: true),
                    "Attempted to copy{0} '{1}'{0} to '{2}'{0} but had an error".format_with(Environment.NewLine, packageResult.InstallLocation, pkgExtensions));

                string logMessage = "Installed/updated extension for {0}. You will be able to use it on next run.".format_with(packageResult.Name);
                this.Log().Warn(logMessage);
                packageResult.Messages.Add(new ResultMessage(ResultType.Note, logMessage));
            }
        }
Example #16
0
        public void serialize <XmlType>(XmlType xmlType, string xmlFilePath, bool isSilent)
        {
            _fileSystem.create_directory_if_not_exists(_fileSystem.get_directory_name(xmlFilePath));

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

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

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

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

                                    return;
                                }

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

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

                                this.Log().Trace("Replacing file '{0}' with '{1}'.".format_with(xmlFilePath, tempUpdateFile));
                                _fileSystem.replace_file(tempUpdateFile, xmlFilePath, xmlFilePath + ".backup");
                            }
                        }
                },
                    errorMessage: "Error serializing type {0}".format_with(typeof(XmlType)),
                    throwError: true,
                    isSilent: isSilent);
            }, MUTEX_TIMEOUT),
                                 waitDurationMilliseconds: 200,
                                 increaseRetryByMilliseconds: 200);
        }
Example #17
0
        public void save_package_information(ChocolateyPackageInformation packageInformation)
        {
            _fileSystem.create_directory_if_not_exists(ApplicationParameters.ChocolateyPackageInfoStoreLocation);
            _fileSystem.ensure_file_attribute_set(ApplicationParameters.ChocolateyPackageInfoStoreLocation, FileAttributes.Hidden);

            if (packageInformation.Package == null)
            {
                this.Log().Debug("No package information to save as package is null.");
                return;
            }

            var pkgStorePath = _fileSystem.combine_paths(ApplicationParameters.ChocolateyPackageInfoStoreLocation, "{0}.{1}".format_with(packageInformation.Package.Id, packageInformation.Package.Version.to_string()));

            _fileSystem.create_directory_if_not_exists(pkgStorePath);

            if (packageInformation.RegistrySnapshot != null)
            {
                _registryService.save_to_file(packageInformation.RegistrySnapshot, _fileSystem.combine_paths(pkgStorePath, REGISTRY_SNAPSHOT_FILE));
            }

            if (packageInformation.FilesSnapshot != null)
            {
                FaultTolerance.try_catch_with_logging_exception(
                    () =>
                {
                    _filesService.save_to_file(packageInformation.FilesSnapshot, _fileSystem.combine_paths(pkgStorePath, FILES_SNAPSHOT_FILE));
                },
                    "Unable to save files snapshot",
                    throwError: false,
                    logWarningInsteadOfError: true
                    );
            }

            if (!string.IsNullOrWhiteSpace(packageInformation.Arguments))
            {
                var argsFile = _fileSystem.combine_paths(pkgStorePath, ARGS_FILE);
                if (_fileSystem.file_exists(argsFile))
                {
                    _fileSystem.delete_file(argsFile);
                }
                _fileSystem.write_file(argsFile, packageInformation.Arguments);
            }
            else
            {
                _fileSystem.delete_file(_fileSystem.combine_paths(pkgStorePath, ARGS_FILE));
            }

            if (!string.IsNullOrWhiteSpace(packageInformation.ExtraInformation))
            {
                var extraFile = _fileSystem.combine_paths(pkgStorePath, EXTRA_FILE);
                if (_fileSystem.file_exists(extraFile))
                {
                    _fileSystem.delete_file(extraFile);
                }
                _fileSystem.write_file(extraFile, packageInformation.ExtraInformation);
            }
            else
            {
                _fileSystem.delete_file(_fileSystem.combine_paths(pkgStorePath, EXTRA_FILE));
            }

            if (packageInformation.VersionOverride != null)
            {
                var versionOverrideFile = _fileSystem.combine_paths(pkgStorePath, VERSION_OVERRIDE_FILE);
                if (_fileSystem.file_exists(versionOverrideFile))
                {
                    _fileSystem.delete_file(versionOverrideFile);
                }
                _fileSystem.write_file(versionOverrideFile, packageInformation.VersionOverride.to_string());
            }
            else
            {
                _fileSystem.delete_file(_fileSystem.combine_paths(pkgStorePath, VERSION_OVERRIDE_FILE));
            }

            if (packageInformation.HasSilentUninstall)
            {
                _fileSystem.write_file(_fileSystem.combine_paths(pkgStorePath, SILENT_UNINSTALLER_FILE), string.Empty, Encoding.ASCII);
            }
            if (packageInformation.IsSideBySide)
            {
                _fileSystem.write_file(_fileSystem.combine_paths(pkgStorePath, SIDE_BY_SIDE_FILE), string.Empty, Encoding.ASCII);
            }
            else
            {
                _fileSystem.delete_file(_fileSystem.combine_paths(pkgStorePath, SIDE_BY_SIDE_FILE));
            }

            if (packageInformation.IsPinned)
            {
                _fileSystem.write_file(_fileSystem.combine_paths(pkgStorePath, PIN_FILE), string.Empty, Encoding.ASCII);
            }
            else
            {
                _fileSystem.delete_file(_fileSystem.combine_paths(pkgStorePath, PIN_FILE));
            }
        }
Example #18
0
        public ChocolateyPackageInformation get_package_information(IPackage package)
        {
            var packageInformation = new ChocolateyPackageInformation(package);

            if (package == null)
            {
                this.Log().Debug("No package information as package is null.");
                return(packageInformation);
            }

            var pkgStorePath = _fileSystem.combine_paths(ApplicationParameters.ChocolateyPackageInfoStoreLocation, "{0}.{1}".format_with(package.Id, package.Version.to_string()));

            if (!_fileSystem.directory_exists(pkgStorePath))
            {
                return(packageInformation);
            }

            var deserializationErrorMessage = @"
A corrupt .registry file exists at {0}.
 Open this file in a text editor, and remove/escape any characters that
 are regarded as illegal within XML strings not surrounded by CData. 
 These are typically the characters &, `<`, and `>`. Again, this
 is an XML document, so you will see many < and > characters, so just
 focus exclusively in the string values not surrounded by CData. Once 
 these have been corrected, rename the .registry.bad file to .registry.
 Once saved, try running the same Chocolatey command that was just 
 executed, so verify problem is fixed.
 NOTE: It will not be possible to rename the file in Windows Explorer.
 Instead, you can use the following PowerShell command:
 Move-Item .\.registry.bad .\.registry
".format_with(_fileSystem.combine_paths(pkgStorePath, REGISTRY_SNAPSHOT_BAD_FILE));

            try
            {
                if (_fileSystem.file_exists(_fileSystem.combine_paths(pkgStorePath, REGISTRY_SNAPSHOT_BAD_FILE)))
                {
                    this.Log().Warn(deserializationErrorMessage);
                }
                else
                {
                    packageInformation.RegistrySnapshot = _registryService.read_from_file(_fileSystem.combine_paths(pkgStorePath, REGISTRY_SNAPSHOT_FILE));
                }
            }
            catch (Exception)
            {
                FaultTolerance.try_catch_with_logging_exception(
                    () =>
                {
                    this.Log().Warn(deserializationErrorMessage);

                    // rename the bad registry file so that it isn't processed again
                    _fileSystem.move_file(_fileSystem.combine_paths(pkgStorePath, REGISTRY_SNAPSHOT_FILE), _fileSystem.combine_paths(pkgStorePath, REGISTRY_SNAPSHOT_BAD_FILE));
                },
                    "Unable to read registry snapshot file for {0} (located at {1})".format_with(package.Id, _fileSystem.combine_paths(pkgStorePath, REGISTRY_SNAPSHOT_FILE)),
                    throwError: false,
                    logWarningInsteadOfError: true,
                    isSilent: true
                    );
            }

            FaultTolerance.try_catch_with_logging_exception(
                () =>
            {
                packageInformation.FilesSnapshot = _filesService.read_from_file(_fileSystem.combine_paths(pkgStorePath, FILES_SNAPSHOT_FILE));
            },
                "Unable to read files snapshot file",
                throwError: false,
                logWarningInsteadOfError: true,
                isSilent: true
                );

            packageInformation.HasSilentUninstall = _fileSystem.file_exists(_fileSystem.combine_paths(pkgStorePath, SILENT_UNINSTALLER_FILE));
            packageInformation.IsSideBySide       = _fileSystem.file_exists(_fileSystem.combine_paths(pkgStorePath, SIDE_BY_SIDE_FILE));
            packageInformation.IsPinned           = _fileSystem.file_exists(_fileSystem.combine_paths(pkgStorePath, PIN_FILE));
            var argsFile = _fileSystem.combine_paths(pkgStorePath, ARGS_FILE);

            if (_fileSystem.file_exists(argsFile))
            {
                packageInformation.Arguments = _fileSystem.read_file(argsFile);
            }
            var extraInfoFile = _fileSystem.combine_paths(pkgStorePath, EXTRA_FILE);

            if (_fileSystem.file_exists(extraInfoFile))
            {
                packageInformation.ExtraInformation = _fileSystem.read_file(extraInfoFile);
            }

            var versionOverrideFile = _fileSystem.combine_paths(pkgStorePath, VERSION_OVERRIDE_FILE);

            if (_fileSystem.file_exists(versionOverrideFile))
            {
                FaultTolerance.try_catch_with_logging_exception(
                    () =>
                {
                    packageInformation.VersionOverride = new SemanticVersion(_fileSystem.read_file(versionOverrideFile).trim_safe());
                },
                    "Unable to read version override file",
                    throwError: false,
                    logWarningInsteadOfError: true
                    );
            }

            return(packageInformation);
        }
Example #19
0
        public ConcurrentDictionary <string, PackageResult> upgrade_run(ChocolateyConfiguration config, Action <PackageResult> continueAction, bool performAction)
        {
            _fileSystem.create_directory_if_not_exists(ApplicationParameters.PackagesLocation);
            var packageInstalls = new ConcurrentDictionary <string, PackageResult>();

            SemanticVersion version        = config.Version != null ? new SemanticVersion(config.Version) : null;
            var             packageManager = NugetCommon.GetPackageManager(
                config,
                _nugetLogger,
                installSuccessAction: (e) =>
            {
                var pkg                 = e.Package;
                var results             = packageInstalls.GetOrAdd(pkg.Id.to_lower(), new PackageResult(pkg, e.InstallPath));
                results.InstallLocation = e.InstallPath;
                results.Messages.Add(new ResultMessage(ResultType.Debug, ApplicationParameters.Messages.ContinueChocolateyAction));

                if (continueAction != null)
                {
                    continueAction.Invoke(results);
                }
            },
                uninstallSuccessAction: null,
                addUninstallHandler: false);

            var configIgnoreDependencies = config.IgnoreDependencies;

            set_package_names_if_all_is_specified(config, () => { config.IgnoreDependencies = true; });
            config.IgnoreDependencies = configIgnoreDependencies;

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

                IPackage installedPackage = packageManager.LocalRepository.FindPackage(packageName);

                if (installedPackage == null)
                {
                    //todo v1 Deprecation - reimplement error
                    //string logMessage = "{0} is not installed. Cannot upgrade a non-existent package.".format_with(packageName);
                    //var results = packageInstalls.GetOrAdd(packageName, new PackageResult(packageName, null, null));
                    //results.Messages.Add(new ResultMessage(ResultType.Error, logMessage));

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

                    string logMessage = @"
DEPRECATION NOTICE - Upgrade will no longer install non-installed 
packages as of version 1.0.0. That is what the install command is for.


{0} is not installed. Installing...".format_with(packageName);

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

                    var packageNames = config.PackageNames;
                    config.PackageNames = packageName;
                    if (config.Noop)
                    {
                        install_noop(config, continueAction);
                    }
                    else
                    {
                        var installResults = install_run(config, continueAction);
                        foreach (var packageResult in installResults)
                        {
                            packageInstalls.GetOrAdd(packageResult.Key, packageResult.Value);
                        }
                    }

                    config.PackageNames = packageNames;
                    continue;
                }

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

                IPackage availablePackage = packageManager.SourceRepository.FindPackage(packageName, version, config.Prerelease, allowUnlisted: false);
                if (availablePackage == null)
                {
                    string logMessage     = "{0} was not found with the source(s) listed.{1} If you specified a particular version and are receiving this message, it is possible that the package name exists but the version does not.{1} Version: \"{2}\"{1} Source(s): \"{3}\"".format_with(packageName, Environment.NewLine, config.Version, config.Sources);
                    var    unfoundResults = packageInstalls.GetOrAdd(packageName, new PackageResult(packageName, version.to_string(), null));

                    if (config.UpgradeCommand.FailOnUnfound)
                    {
                        unfoundResults.Messages.Add(new ResultMessage(ResultType.Error, logMessage));
                        if (config.RegularOuptut)
                        {
                            this.Log().Error(ChocolateyLoggers.Important, logMessage);
                        }
                    }
                    else
                    {
                        unfoundResults.Messages.Add(new ResultMessage(ResultType.Warn, logMessage));
                        unfoundResults.Messages.Add(new ResultMessage(ResultType.Inconclusive, logMessage));
                        if (config.RegularOuptut)
                        {
                            this.Log().Warn(ChocolateyLoggers.Important, logMessage);
                        }
                    }

                    continue;
                }

                if (pkgInfo != null && pkgInfo.IsSideBySide)
                {
                    //todo: get smarter about realizing multiple versions have been installed before and allowing that
                }

                var results = packageInstalls.GetOrAdd(packageName, new PackageResult(availablePackage, _fileSystem.combine_paths(ApplicationParameters.PackagesLocation, availablePackage.Id)));

                if ((installedPackage.Version > availablePackage.Version))
                {
                    string logMessage = "{0} v{1} is newer than the most recent.{2} You must be smarter than the average bear...".format_with(installedPackage.Id, installedPackage.Version, Environment.NewLine);
                    results.Messages.Add(new ResultMessage(ResultType.Inconclusive, logMessage));

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

                if (installedPackage.Version == availablePackage.Version)
                {
                    string logMessage = "{0} v{1} is the latest version available based on your source(s).".format_with(installedPackage.Id, installedPackage.Version);

                    if (!config.Force)
                    {
                        if (results.Messages.Count((p) => p.Message == ApplicationParameters.Messages.ContinueChocolateyAction) == 0)
                        {
                            results.Messages.Add(new ResultMessage(ResultType.Inconclusive, logMessage));
                        }

                        if (config.RegularOuptut)
                        {
                            this.Log().Info(logMessage);
                        }
                        continue;
                    }

                    results.Messages.Add(new ResultMessage(ResultType.Note, logMessage));
                    if (config.RegularOuptut)
                    {
                        this.Log().Info(logMessage);
                    }
                }

                if ((availablePackage.Version > installedPackage.Version) || config.Force)
                {
                    if (availablePackage.Version > installedPackage.Version)
                    {
                        string logMessage = "You have {0} v{1} installed. Version {2} is available based on your source(s)".format_with(installedPackage.Id, installedPackage.Version, availablePackage.Version);
                        results.Messages.Add(new ResultMessage(ResultType.Note, logMessage));

                        if (config.RegularOuptut)
                        {
                            this.Log().Warn(logMessage);
                        }
                        else
                        {
                            //last one is whether this package is pinned or not
                            this.Log().Info("{0}|{1}|{2}|{3}".format_with(installedPackage.Id, installedPackage.Version, availablePackage.Version, "false"));
                        }
                    }

                    if (performAction)
                    {
                        try
                        {
                            using (packageManager.SourceRepository.StartOperation(
                                       RepositoryOperationNames.Update,
                                       packageName,
                                       version == null ? null : version.ToString()))
                            {
                                rename_legacy_package_version(config, installedPackage, pkgInfo);
                                backup_existing_version(config, installedPackage);
                                if (config.Force && (installedPackage.Version == availablePackage.Version))
                                {
                                    FaultTolerance.try_catch_with_logging_exception(
                                        () => _fileSystem.delete_directory_if_exists(_fileSystem.combine_paths(ApplicationParameters.PackagesLocation, installedPackage.Id), recursive: true),
                                        "Error during force upgrade");
                                    packageManager.InstallPackage(availablePackage, config.IgnoreDependencies, config.Prerelease);
                                }
                                else
                                {
                                    packageManager.UpdatePackage(availablePackage, updateDependencies: !config.IgnoreDependencies, allowPrereleaseVersions: config.Prerelease);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            var logMessage = "{0} not upgraded. An error occurred during installation:{1} {2}".format_with(packageName, Environment.NewLine, ex.Message);
                            this.Log().Error(ChocolateyLoggers.Important, logMessage);
                            results.Messages.Add(new ResultMessage(ResultType.Error, logMessage));
                            if (continueAction != null)
                            {
                                continueAction.Invoke(results);
                            }
                        }
                    }
                }
            }

            return(packageInstalls);
        }
Example #20
0
        /// <summary>
        ///   Evaluates registry keys and updates the snapshop with items
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="snapshot">The snapshot.</param>
        public void evaluate_keys(RegistryKey key, Registry snapshot)
        {
            if (key == null)
            {
                return;
            }

            FaultTolerance.try_catch_with_logging_exception(
                () =>
            {
                foreach (var subKeyName in key.GetSubKeyNames())
                {
                    FaultTolerance.try_catch_with_logging_exception(
                        () => evaluate_keys(key.OpenSubKey(subKeyName, RegistryKeyPermissionCheck.ReadSubTree, RegistryRights.ReadKey), snapshot),
                        "Failed to open subkey named '{0}' for '{1}', likely due to permissions".format_with(subKeyName, key.Name),
                        logWarningInsteadOfError: true);
                }
            },
                "Failed to open subkeys for '{0}', likely due to permissions".format_with(key.Name),
                logWarningInsteadOfError: true);

            var appKey = new RegistryApplicationKey
            {
                KeyPath      = key.Name,
                RegistryView = key.View,
                DefaultValue = key.GetValue("").to_string(),
                DisplayName  = key.GetValue("DisplayName").to_string()
            };

            if (string.IsNullOrWhiteSpace(appKey.DisplayName))
            {
                appKey.DisplayName = appKey.DefaultValue;
            }

            if (!string.IsNullOrWhiteSpace(appKey.DisplayName))
            {
                appKey.InstallLocation = key.GetValue("InstallLocation").to_string();
                appKey.UninstallString = key.GetValue("UninstallString").to_string();
                if (key.GetValue("QuietUninstallString") != null)
                {
                    appKey.UninstallString   = key.GetValue("QuietUninstallString").to_string();
                    appKey.HasQuietUninstall = true;
                }

                // informational
                appKey.Publisher     = key.GetValue("Publisher").to_string();
                appKey.InstallDate   = key.GetValue("InstallDate").to_string();
                appKey.InstallSource = key.GetValue("InstallSource").to_string();
                appKey.Language      = key.GetValue("Language").to_string();

                // Version
                appKey.DisplayVersion = key.GetValue("DisplayVersion").to_string();
                appKey.Version        = key.GetValue("Version").to_string();
                appKey.VersionMajor   = key.GetValue("VersionMajor").to_string();
                appKey.VersionMinor   = key.GetValue("VersionMinor").to_string();

                // installinformation
                appKey.SystemComponent  = key.GetValue("SystemComponent").to_string() == "1";
                appKey.WindowsInstaller = key.GetValue("WindowsInstaller").to_string() == "1";
                appKey.NoRemove         = key.GetValue("NoRemove").to_string() == "1";
                appKey.NoModify         = key.GetValue("NoModify").to_string() == "1";
                appKey.NoRepair         = key.GetValue("NoRepair").to_string() == "1";
                appKey.ReleaseType      = key.GetValue("ReleaseType").to_string();
                appKey.ParentKeyName    = key.GetValue("ParentKeyName").to_string();

                if (appKey.WindowsInstaller || appKey.UninstallString.to_lower().Contains("msiexec"))
                {
                    appKey.InstallerType = InstallerType.Msi;
                }

                if (key.Name.EndsWith("_is1") || !string.IsNullOrWhiteSpace(key.GetValue("Inno Setup: Setup Version").to_string()))
                {
                    appKey.InstallerType = InstallerType.InnoSetup;
                }

                if (key.GetValue("dwVersionMajor") != null)
                {
                    appKey.InstallerType   = InstallerType.Nsis;
                    appKey.VersionMajor    = key.GetValue("dwVersionMajor").to_string();
                    appKey.VersionMinor    = key.GetValue("dwVersionMinor").to_string();
                    appKey.VersionRevision = key.GetValue("dwVersionRev").to_string();
                    appKey.VersionBuild    = key.GetValue("dwVersionBuild").to_string();
                }
                if (appKey.ReleaseType.is_equal_to("Hotfix") || appKey.ReleaseType.is_equal_to("Update Rollup") || appKey.ReleaseType.is_equal_to("Security Update") || appKey.DefaultValue.to_string().StartsWith("KB", ignoreCase: true, culture: CultureInfo.InvariantCulture))
                {
                    appKey.InstallerType = InstallerType.HotfixOrSecurityUpdate;
                }
                if (appKey.ReleaseType.is_equal_to("ServicePack"))
                {
                    appKey.InstallerType = InstallerType.ServicePack;
                }

                // assume NSIS if we still don't know and we find uninst.exe
                if (appKey.InstallerType == InstallerType.Unknown && appKey.UninstallString.to_lower().Contains("uninst.exe"))
                {
                    appKey.InstallerType = InstallerType.Nsis;
                }

                if (appKey.InstallerType == InstallerType.Unknown && appKey.HasQuietUninstall)
                {
                    appKey.InstallerType = InstallerType.Custom;
                }

                if (_logOutput)
                {
                    if (appKey.is_in_programs_and_features() && appKey.InstallerType == InstallerType.Unknown)
                    {
                        foreach (var name in key.GetValueNames())
                        {
                            //var kind = key.GetValueKind(name);
                            var value = key.GetValue(name);
                            if (name.is_equal_to("QuietUninstallString") || name.is_equal_to("UninstallString"))
                            {
                                Console.WriteLine("key - {0}|{1}={2}|Type detected={3}".format_with(key.Name, name, value.to_string(), appKey.InstallerType.to_string()));
                            }

                            //Console.WriteLine("key - {0}, name - {1}, kind - {2}, value - {3}".format_with(key.Name, name, kind, value.to_string()));
                        }
                    }
                }

                snapshot.RegistryKeys.Add(appKey);
            }

            key.Close();
            key.Dispose();
        }
        private void get_msi_information(RegistryApplicationKey appKey, RegistryKey key)
        {
            _componentLoopCount = 0;

            var userDataProductKeyId = get_msi_user_data_key(key.Name);

            if (string.IsNullOrWhiteSpace(userDataProductKeyId))
            {
                return;
            }

            var hklm = open_key(RegistryHive.LocalMachine, RegistryView.Default);

            if (Environment.Is64BitOperatingSystem)
            {
                hklm = open_key(RegistryHive.LocalMachine, RegistryView.Registry64);
            }

            FaultTolerance.try_catch_with_logging_exception(
                () =>
            {
                var msiRegistryKey = hklm.OpenSubKey(UNINSTALLER_MSI_MACHINE_KEY_NAME, RegistryKeyPermissionCheck.ReadSubTree, RegistryRights.ReadKey);
                if (msiRegistryKey == null)
                {
                    return;
                }

                foreach (var subKeyName in msiRegistryKey.GetSubKeyNames())
                {
                    var msiProductKey = FaultTolerance.try_catch_with_logging_exception(
                        () => msiRegistryKey.OpenSubKey("{0}\\Products\\{1}\\InstallProperties".format_with(subKeyName, userDataProductKeyId), RegistryKeyPermissionCheck.ReadSubTree, RegistryRights.ReadKey),
                        "Failed to open subkey named '{0}' for '{1}', likely due to permissions".format_with(subKeyName, msiRegistryKey.Name),
                        logWarningInsteadOfError: true);
                    if (msiProductKey == null)
                    {
                        continue;
                    }

                    appKey.InstallLocation = set_if_empty(appKey.InstallLocation, msiProductKey.get_value_as_string("InstallLocation"));
                    // informational
                    appKey.Publisher     = set_if_empty(appKey.Publisher, msiProductKey.get_value_as_string("Publisher"));
                    appKey.InstallDate   = set_if_empty(appKey.InstallDate, msiProductKey.get_value_as_string("InstallDate"));
                    appKey.InstallSource = set_if_empty(appKey.InstallSource, msiProductKey.get_value_as_string("InstallSource"));
                    appKey.Language      = set_if_empty(appKey.Language, msiProductKey.get_value_as_string("Language"));
                    appKey.LocalPackage  = set_if_empty(appKey.LocalPackage, msiProductKey.get_value_as_string("LocalPackage"));

                    // Version
                    appKey.DisplayVersion = set_if_empty(appKey.DisplayVersion, msiProductKey.get_value_as_string("DisplayVersion"));
                    appKey.Version        = set_if_empty(appKey.Version, msiProductKey.get_value_as_string("Version"));
                    appKey.VersionMajor   = set_if_empty(appKey.VersionMajor, msiProductKey.get_value_as_string("VersionMajor"));
                    appKey.VersionMinor   = set_if_empty(appKey.VersionMinor, msiProductKey.get_value_as_string("VersionMinor"));

                    // search components for install location if still empty
                    // the performance of this is very bad - without this the query is sub-second
                    // with this it takes about 15 seconds with around 200 apps installed
                    //if (string.IsNullOrWhiteSpace(appKey.InstallLocation) && !appKey.Publisher.contains("Microsoft"))
                    //{
                    //    var msiComponentsKey = FaultTolerance.try_catch_with_logging_exception(
                    //       () => msiRegistryKey.OpenSubKey("{0}\\Components".format_with(subKeyName), RegistryKeyPermissionCheck.ReadSubTree, RegistryRights.ReadKey),
                    //       "Failed to open subkey named '{0}' for '{1}', likely due to permissions".format_with(subKeyName, msiRegistryKey.Name),
                    //       logWarningInsteadOfError: true);
                    //    if (msiComponentsKey == null) continue;

                    //    foreach (var msiComponentKeyName in msiComponentsKey.GetSubKeyNames())
                    //    {
                    //        var msiComponentKey = FaultTolerance.try_catch_with_logging_exception(
                    //           () => msiComponentsKey.OpenSubKey(msiComponentKeyName, RegistryKeyPermissionCheck.ReadSubTree, RegistryRights.ReadKey),
                    //           "Failed to open subkey named '{0}' for '{1}', likely due to permissions".format_with(subKeyName, msiRegistryKey.Name),
                    //           logWarningInsteadOfError: true);

                    //        if (msiComponentKey.GetValueNames().Contains(userDataProductKeyId, StringComparer.OrdinalIgnoreCase))
                    //        {
                    //            _componentLoopCount++;
                    //            appKey.InstallLocation = set_if_empty(appKey.InstallLocation, get_install_location_estimate(msiComponentKey.get_value(userDataProductKeyId)));
                    //            if (!string.IsNullOrWhiteSpace(appKey.InstallLocation)) break;
                    //            if (_componentLoopCount >= 10) break;
                    //        }
                    //    }
                    //}
                }
            },
                "Failed to open subkeys for '{0}', likely due to permissions".format_with(hklm.Name),
                logWarningInsteadOfError: 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 #23
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 #24
0
        public ConcurrentDictionary <string, PackageResult> install_run(ChocolateyConfiguration config, Action <PackageResult> continueAction)
        {
            _fileSystem.create_directory_if_not_exists(ApplicationParameters.PackagesLocation);
            var packageInstalls = new ConcurrentDictionary <string, PackageResult>();

            //todo: handle all

            SemanticVersion version = config.Version != null ? new SemanticVersion(config.Version) : null;

            IList <string> packageNames = config.PackageNames.Split(new[] { ApplicationParameters.PackageNamesSeparator }, StringSplitOptions.RemoveEmptyEntries).or_empty_list_if_null().ToList();

            if (packageNames.Count == 1)
            {
                var packageName = packageNames.DefaultIfEmpty(string.Empty).FirstOrDefault();
                if (packageName.EndsWith(Constants.PackageExtension) || packageName.EndsWith(Constants.ManifestExtension))
                {
                    this.Log().Debug("Updating source and package name to handle *.nupkg or *.nuspec file.");
                    packageNames.Clear();
                    packageNames.Add(_fileSystem.get_file_name_without_extension(packageName));
                    config.Sources = _fileSystem.get_directory_name(_fileSystem.get_full_path(packageName));

                    if (packageName.EndsWith(Constants.ManifestExtension))
                    {
                        this.Log().Debug("Building nuspec file prior to install.");
                        config.Input = packageName;
                        // build package
                        pack_run(config);
                    }
                }
            }

            // this is when someone points the source directly at a nupkg
            // e.g. -s c:\somelocation\somwere\packagename.nupkg
            if (config.Sources.to_string().EndsWith(Constants.PackageExtension))
            {
                config.Sources = _fileSystem.get_directory_name(_fileSystem.get_full_path(config.Sources));
            }

            var packageManager = NugetCommon.GetPackageManager(
                config, _nugetLogger,
                installSuccessAction: (e) =>
            {
                var pkg                 = e.Package;
                var results             = packageInstalls.GetOrAdd(pkg.Id.to_lower(), new PackageResult(pkg, e.InstallPath));
                results.InstallLocation = e.InstallPath;
                results.Messages.Add(new ResultMessage(ResultType.Debug, ApplicationParameters.Messages.ContinueChocolateyAction));

                if (continueAction != null)
                {
                    continueAction.Invoke(results);
                }
            },
                uninstallSuccessAction: null,
                addUninstallHandler: true);


            foreach (string packageName in packageNames.or_empty_list_if_null())
            {
                //todo: get smarter about realizing multiple versions have been installed before and allowing that

                remove_rollback_directory_if_exists(packageName);

                IPackage installedPackage = packageManager.LocalRepository.FindPackage(packageName);

                if (installedPackage != null && (version == null || version == installedPackage.Version) && !config.Force)
                {
                    string logMessage = "{0} v{1} already installed.{2} Use --force to reinstall, specify a version to install, or try upgrade.".format_with(installedPackage.Id, installedPackage.Version, Environment.NewLine);
                    var    results    = packageInstalls.GetOrAdd(packageName, new PackageResult(installedPackage, _fileSystem.combine_paths(ApplicationParameters.PackagesLocation, installedPackage.Id)));
                    results.Messages.Add(new ResultMessage(ResultType.Warn, logMessage));
                    results.Messages.Add(new ResultMessage(ResultType.Inconclusive, logMessage));
                    this.Log().Warn(ChocolateyLoggers.Important, logMessage);
                    continue;
                }

                if (installedPackage != null && (version == null || version == installedPackage.Version) && config.Force)
                {
                    this.Log().Debug(() => "{0} v{1} already installed. Forcing reinstall.".format_with(installedPackage.Id, installedPackage.Version));
                    version = installedPackage.Version;
                }

                IPackage availablePackage = packageManager.SourceRepository.FindPackage(packageName, version, config.Prerelease, allowUnlisted: false);
                if (availablePackage == null)
                {
                    var logMessage = "{0} not installed. The package was not found with the source(s) listed.{1} If you specified a particular version and are receiving this message, it is possible that the package name exists but the version does not.{1} Version: \"{2}\"{1} Source(s): \"{3}\"".format_with(packageName, Environment.NewLine, config.Version, config.Sources);
                    this.Log().Error(ChocolateyLoggers.Important, logMessage);
                    var results = packageInstalls.GetOrAdd(packageName, new PackageResult(packageName, version.to_string(), null));
                    results.Messages.Add(new ResultMessage(ResultType.Error, logMessage));
                    continue;
                }

                if (installedPackage != null && (installedPackage.Version == availablePackage.Version))
                {
                    backup_existing_version(config, installedPackage);

                    FaultTolerance.try_catch_with_logging_exception(
                        () => packageManager.UninstallPackage(installedPackage, forceRemove: config.Force, removeDependencies: config.ForceDependencies),
                        "Unable to remove existing package prior to forced reinstall",
                        logWarningInsteadOfError: true);
                }

                try
                {
                    using (packageManager.SourceRepository.StartOperation(
                               RepositoryOperationNames.Install,
                               packageName,
                               version == null ? null : version.ToString()))
                    {
                        packageManager.InstallPackage(availablePackage, ignoreDependencies: config.IgnoreDependencies, allowPrereleaseVersions: config.Prerelease);
                        //packageManager.InstallPackage(packageName, version, configuration.IgnoreDependencies, configuration.Prerelease);
                    }
                }
                catch (Exception ex)
                {
                    var logMessage = "{0} not installed. An error occurred during installation:{1} {2}".format_with(packageName, Environment.NewLine, ex.Message);
                    this.Log().Error(ChocolateyLoggers.Important, logMessage);
                    var results = packageInstalls.GetOrAdd(packageName, new PackageResult(packageName, version.to_string(), null));
                    results.Messages.Add(new ResultMessage(ResultType.Error, logMessage));
                    if (continueAction != null)
                    {
                        continueAction.Invoke(results);
                    }
                }
            }

            return(packageInstalls);
        }
Example #25
0
        /// <summary>
        ///   Evaluates registry keys and updates the snapshop with items
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="snapshot">The snapshot.</param>
        public void evaluate_keys(RegistryKeyInfo regkey, RegistryKey key, Registry snapshot,
                                  string packageId = null, string version = null, bool?nugetInstallable = null)
        {
            if (key == null)
            {
                return;
            }

            FaultTolerance.try_catch_with_logging_exception(
                () =>
            {
                Regex reMatchFile = null;

                if (packageId != null)
                {
                    reMatchFile = FindFilesPatternToRegex.Convert(packageId);
                }

                foreach (var subKeyName in key.GetSubKeyNames())
                {
                    if (reMatchFile != null && !reMatchFile.IsMatch(subKeyName))
                    {
                        continue;
                    }

                    regkey.SubKeyName = subKeyName;

                    FaultTolerance.try_catch_with_logging_exception(
                        () => evaluate_keys(regkey, key.OpenSubKey(subKeyName, RegistryKeyPermissionCheck.ReadSubTree, RegistryRights.ReadKey), snapshot, packageId, version, nugetInstallable),
                        "Failed to open subkey named '{0}' for '{1}', likely due to permissions".format_with(subKeyName, key.Name),
                        logWarningInsteadOfError: true);
                }
            },
                "Failed to open subkeys for '{0}', likely due to permissions".format_with(key.Name),
                logWarningInsteadOfError: true);

            var appKey = new RegistryApplicationKey
            {
                Hive         = regkey.hive,
                KeyPath      = key.Name,
                RegistryView = key.View,
                DefaultValue = key.get_value_as_string(""),
                DisplayName  = key.get_value_as_string("DisplayName")
            };

            if (string.IsNullOrWhiteSpace(appKey.DisplayName))
            {
                appKey.DisplayName = appKey.DefaultValue;
            }

            bool addRegEntry = false;

            if (!string.IsNullOrWhiteSpace(appKey.DisplayName))
            {
                addRegEntry      = true;
                appKey.PackageId = key.get_value_as_string("PackageId");
                if (string.IsNullOrWhiteSpace(appKey.PackageId))
                {
                    appKey.PackageId = regkey.SubKeyName;
                }

                string s = key.get_value_as_string(nameof(RegistryApplicationKey.IsPinned));
                if (string.IsNullOrWhiteSpace(s))
                {
                    appKey.IsPinned = false;
                }
                else
                {
                    appKey.IsPinned = s != "0";
                }
                appKey.InstallLocation = key.get_value_as_string("InstallLocation");

                if (nugetInstallable.HasValue)
                {
                    string dir = appKey.InstallLocation;
                    bool   isNugetInstallable = false;

                    if (!String.IsNullOrEmpty(dir))
                    {
                        string parentDir     = System.IO.Path.GetDirectoryName(dir);
                        string parentDirName = System.IO.Path.GetFileName(dir);
                        if (parentDirName == appKey.PackageId)
                        {
                            string nuspecPath = System.IO.Path.Combine(dir, appKey.PackageId + NuGet.Constants.ManifestExtension);
                            isNugetInstallable = System.IO.File.Exists(nuspecPath);
                        }
                    }

                    if (nugetInstallable.Value != isNugetInstallable)
                    {
                        addRegEntry = false;
                    }
                }
            }

            if (addRegEntry)
            {
                appKey.UninstallString = key.get_value_as_string("UninstallString");
                if (!string.IsNullOrWhiteSpace(key.get_value_as_string("QuietUninstallString")))
                {
                    appKey.UninstallString   = key.get_value_as_string("QuietUninstallString");
                    appKey.HasQuietUninstall = true;
                }

                // informational
                appKey.Publisher     = key.get_value_as_string("Publisher");
                appKey.InstallDate   = key.get_value_as_string("InstallDate");
                appKey.InstallSource = key.get_value_as_string("InstallSource");
                appKey.Language      = key.get_value_as_string("Language");

                // Version
                appKey.DisplayVersion = key.get_value_as_string("DisplayVersion");
                appKey.Version        = key.get_value_as_string("Version");
                appKey.VersionMajor   = key.get_value_as_string("VersionMajor");
                appKey.VersionMinor   = key.get_value_as_string("VersionMinor");

                // installinformation
                appKey.SystemComponent  = key.get_value_as_string("SystemComponent") == "1";
                appKey.WindowsInstaller = key.get_value_as_string("WindowsInstaller") == "1";
                appKey.NoRemove         = key.get_value_as_string("NoRemove") == "1";
                appKey.NoModify         = key.get_value_as_string("NoModify") == "1";
                appKey.NoRepair         = key.get_value_as_string("NoRepair") == "1";
                appKey.ReleaseType      = key.get_value_as_string("ReleaseType");
                appKey.ParentKeyName    = key.get_value_as_string("ParentKeyName");
                appKey.DisplayIcon      = key.get_value_as_string("DisplayIcon");
                long size = 0;
                if (long.TryParse(key.get_value_as_string("EstimatedSize"), out size))
                {
                    appKey.EstimatedSize = size;
                }

                if (appKey.WindowsInstaller || appKey.UninstallString.to_string().to_lower().Contains("msiexec"))
                {
                    appKey.InstallerType = InstallerType.Msi;
                }

                if (key.Name.EndsWith("_is1") || !string.IsNullOrWhiteSpace(key.get_value_as_string("Inno Setup: Setup Version")))
                {
                    appKey.InstallerType = InstallerType.InnoSetup;
                }

                if (!string.IsNullOrWhiteSpace(key.get_value_as_string("dwVersionMajor")))
                {
                    appKey.InstallerType   = InstallerType.Nsis;
                    appKey.VersionMajor    = key.get_value_as_string("dwVersionMajor");
                    appKey.VersionMinor    = key.get_value_as_string("dwVersionMinor");
                    appKey.VersionRevision = key.get_value_as_string("dwVersionRev");
                    appKey.VersionBuild    = key.get_value_as_string("dwVersionBuild");
                }
                if (appKey.ReleaseType.is_equal_to("Hotfix") || appKey.ReleaseType.is_equal_to("Update Rollup") || appKey.ReleaseType.is_equal_to("Security Update") || appKey.DefaultValue.to_string().StartsWith("KB", ignoreCase: true, culture: CultureInfo.InvariantCulture))
                {
                    appKey.InstallerType = InstallerType.HotfixOrSecurityUpdate;
                }
                if (appKey.ReleaseType.is_equal_to("ServicePack"))
                {
                    appKey.InstallerType = InstallerType.ServicePack;
                }

                // assume NSIS if we still don't know and we find uninst.exe
                if (appKey.InstallerType == InstallerType.Unknown && appKey.UninstallString.to_string().to_lower().Contains("uninst.exe"))
                {
                    appKey.InstallerType = InstallerType.Nsis;
                }

                if (appKey.InstallerType == InstallerType.Unknown && appKey.HasQuietUninstall)
                {
                    appKey.InstallerType = InstallerType.Custom;
                }

                if (appKey.InstallerType == InstallerType.Msi)
                {
                    get_msi_information(appKey, key);
                }

                if (_logOutput)
                {
                    //if (appKey.is_in_programs_and_features() && appKey.InstallerType == InstallerType.Unknown)
                    //{
                    foreach (var name in key.GetValueNames())
                    {
                        //var kind = key.GetValueKind(name);
                        var value = key.get_value_as_string(name);
                        if (name.is_equal_to("QuietUninstallString") || name.is_equal_to("UninstallString"))
                        {
                            Console.WriteLine("key - {0}|{1}={2}|Type detected={3}|install location={4}".format_with(key.Name, name, value.to_string(), appKey.InstallerType.to_string(), appKey.InstallLocation.to_string()));
                        }

                        //Console.WriteLine("key - {0}, name - {1}, kind - {2}, value - {3}".format_with(key.Name, name, kind, value.to_string()));
                    }
                    //}
                }

                snapshot.RegistryKeys.Add(appKey);
            }

            key.Close();
            key.Dispose();
        }
Example #26
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");
                }
            }
        }
Example #27
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
                );
        }