public VagrantService(ICommandExecutor commandExecutor, IFileSystem fileSystem, IConfigurationSettings configuration) { _commandExecutor = commandExecutor; _fileSystem = fileSystem; _configuration = configuration; var vagrantFound = false; var customVagrantPath = _configuration.PathToVagrant; if (!string.IsNullOrWhiteSpace(customVagrantPath)) { if (!_fileSystem.file_exists(customVagrantPath)) { this.Log().Warn("Unable to find vagrant at the path specified. Using default instance."); } else { this.Log().Warn("Using custom vagrant path at '{0}'.".format_with(customVagrantPath)); vagrantFound = true; _vagrantExecutable = customVagrantPath; } } if (!vagrantFound) { _vagrantExecutable = @"C:\HashiCorp\Vagrant\bin\vagrant.exe"; if (!_fileSystem.file_exists(_vagrantExecutable)) { _vagrantExecutable = _fileSystem.get_executable_path("vagrant.exe"); } } //use_vagrant_directly(); }
/// <summary> /// Extract binary file from an assembly to a location on disk /// </summary> /// <param name="fileSystem">The file system.</param> /// <param name="assembly">The assembly.</param> /// <param name="manifestLocation">The manifest location.</param> /// <param name="filePath">The file path.</param> /// <param name="overwriteExisting"> /// if set to <c>true</c> [overwrite existing]. /// </param> public static void extract_binary_file_from_assembly(IFileSystem fileSystem, IAssembly assembly, string manifestLocation, string filePath, bool overwriteExisting = false) { if (overwriteExisting || !fileSystem.file_exists(filePath)) { fileSystem.create_directory_if_not_exists(fileSystem.get_directory_name(filePath)); fileSystem.write_file(filePath, () => assembly.get_manifest_stream(manifestLocation)); } }
public void delete_file(string folderName, string fileName) { if (String.IsNullOrWhiteSpace(folderName)) { throw new ArgumentNullException("folderName"); } if (String.IsNullOrWhiteSpace(fileName)) { throw new ArgumentNullException("fileName"); } var path = build_path(configuration.ImagesFolder, folderName, fileName); if (fileSystemSvc.file_exists(path)) { fileSystemSvc.delete_file(path); } }
public PackageFiles read_from_file(string filePath) { if (!_fileSystem.file_exists(filePath)) { return(null); } return(_xmlService.deserialize <PackageFiles>(filePath)); }
private void DetermineIfChocolateyExecutableIsBeingUsed() { var exePath = _fileSystem.combine_paths(ChocolateyInstall, "choco.exe"); if (_fileSystem.file_exists(exePath)) { IsChocolateyExecutableBeingUsed = true; } }
public Registry read_from_file(string filePath) { if (!_fileSystem.file_exists(filePath)) { return(null); } return(_xmlService.deserialize <Registry>(filePath)); }
public static string get_powershell_location(IFileSystem fileSystem) { foreach (var powershellLocation in _powershellLocations) { if (fileSystem.file_exists(powershellLocation)) return powershellLocation; } var message = "Unable to find suitable location for PowerShell. Searched the following locations: '{0}'".format_with(string.Join("; ", _powershellLocations)); "PowerShellExecutor".Log().Error(message); throw new FileNotFoundException(message); }
public static string get_powershell_location(IFileSystem fileSystem) { foreach (var powershellLocation in _powershellLocations) { if (fileSystem.file_exists(powershellLocation)) { return(powershellLocation); } } throw new FileNotFoundException("Unable to find suitable location for PowerShell. Searched the following locations: '{0}'".format_with(string.Join("; ", _powershellLocations))); }
public static string get_powershell_location(IFileSystem fileSystem) { foreach (var powershellLocation in _powershellLocations) { if (fileSystem.file_exists(powershellLocation)) { return powershellLocation; } } throw new FileNotFoundException("Unable to find suitable location for PowerShell. Searched the following locations: '{0}'".format_with(string.Join("; ", _powershellLocations))); }
public XmlType deserialize <XmlType>(string xmlFilePath) { return(FaultTolerance.try_catch_with_logging_exception( () => { var xmlSerializer = new XmlSerializer(typeof(XmlType)); using (var fileStream = _fileSystem.open_file_readonly(xmlFilePath)) using (var fileReader = new StreamReader(fileStream)) using (var xmlReader = XmlReader.Create(fileReader)) { if (!xmlSerializer.CanDeserialize(xmlReader)) { this.Log().Warn("Cannot deserialize response of type {0}", typeof(XmlType)); return default(XmlType); } try { return (XmlType)xmlSerializer.Deserialize(xmlReader); } catch (InvalidOperationException ex) { // Check if its just a malformed document. if (ex.Message.Contains("There is an error in XML document")) { // If so, check for a backup file and try an parse that. if (_fileSystem.file_exists(xmlFilePath + ".backup")) { using (var backupStream = _fileSystem.open_file_readonly(xmlFilePath + ".backup")) using (var backupReader = new StreamReader(backupStream)) using (var backupXmlReader = XmlReader.Create(backupReader)) { var validConfig = (XmlType)xmlSerializer.Deserialize(backupXmlReader); // If there's no errors and it's valid, go ahead and replace the bad file with the backup. if (validConfig != null) { _fileSystem.copy_file(xmlFilePath + ".backup", xmlFilePath, overwriteExisting: true); } return validConfig; } } } throw; } } }, "Error deserializing response of type {0}".format_with(typeof(XmlType)), throwError: true)); }
public static void validate(IFileSystem fileSystem) { string licenseFile = ApplicationParameters.LicenseFileLocation; if (fileSystem.file_exists(licenseFile)) { new LicenseValidator(PUBLIC_KEY, licenseFile).AssertValidLicense(); } else { //free version } }
/// <summary> /// Extract text file from assembly to location on disk. /// </summary> /// <param name="fileSystem">The file system.</param> /// <param name="assembly">The assembly.</param> /// <param name="manifestLocation">The manifest location.</param> /// <param name="filePath">The file path.</param> /// <param name="overwriteExisting"> /// if set to <c>true</c> [overwrite existing]. /// </param> /// <exception cref="System.IO.FileNotFoundException"></exception> public static void extract_text_file_from_assembly(IFileSystem fileSystem, IAssembly assembly, string manifestLocation, string filePath, bool overwriteExisting = false) { if (overwriteExisting || !fileSystem.file_exists(filePath)) { fileSystem.create_directory_if_not_exists(fileSystem.get_directory_name(filePath)); var fileText = assembly.get_manifest_string(manifestLocation); if (string.IsNullOrWhiteSpace(fileText)) { string errorMessage = "Could not find a file in the manifest resource stream of '{0}' at '{1}'.".format_with(assembly.FullName, manifestLocation); "chocolatey".Log().Error(() => errorMessage); throw new FileNotFoundException(errorMessage); } fileSystem.write_file(filePath, fileText, Encoding.UTF8); } }
/// <summary> /// Extract binary file from an assembly to a location on disk /// </summary> /// <param name="fileSystem">The file system.</param> /// <param name="assembly">The assembly.</param> /// <param name="manifestLocation">The manifest location.</param> /// <param name="filePath">The file path.</param> /// <param name="overwriteExisting"> /// if set to <c>true</c> [overwrite existing]. /// </param> /// <param name="throwEror">Throw an error if there are issues</param> public static void extract_binary_file_from_assembly(IFileSystem fileSystem, IAssembly assembly, string manifestLocation, string filePath, bool overwriteExisting = false, bool throwEror = true) { if (overwriteExisting || !fileSystem.file_exists(filePath)) { FaultTolerance.try_catch_with_logging_exception( () => { fileSystem.create_directory_if_not_exists(fileSystem.get_directory_name(filePath)); fileSystem.write_file(filePath, () => assembly.get_manifest_stream(manifestLocation)); }, errorMessage: "Unable to extract binary", throwError: throwEror, logWarningInsteadOfError: false, logDebugInsteadOfError: !throwEror, isSilent: !throwEror); } }
private IEnumerable <ChocolateyConfiguration> get_packages_from_config(string packageConfigFile, ChocolateyConfiguration config, ConcurrentDictionary <string, PackageResult> packageInstalls) { IList <ChocolateyConfiguration> packageConfigs = new List <ChocolateyConfiguration>(); if (!_fileSystem.file_exists(_fileSystem.get_full_path(packageConfigFile))) { var logMessage = "Could not find '{0}' in the location specified.".format_with(packageConfigFile); this.Log().Error(ChocolateyLoggers.Important, logMessage); var results = packageInstalls.GetOrAdd(packageConfigFile, new PackageResult(packageConfigFile, null, null)); results.Messages.Add(new ResultMessage(ResultType.Error, logMessage)); return(packageConfigs); } var settings = _xmlService.deserialize <PackagesConfigFileSettings>(_fileSystem.get_full_path(packageConfigFile)); foreach (var pkgSettings in settings.Packages.or_empty_list_if_null()) { if (!pkgSettings.Disabled) { var packageConfig = config.deep_copy(); packageConfig.PackageNames = pkgSettings.Id; packageConfig.Sources = string.IsNullOrWhiteSpace(pkgSettings.Source) ? packageConfig.Sources : pkgSettings.Source; packageConfig.Version = pkgSettings.Version; packageConfig.InstallArguments = string.IsNullOrWhiteSpace(pkgSettings.InstallArguments) ? packageConfig.InstallArguments : pkgSettings.InstallArguments; packageConfig.PackageParameters = string.IsNullOrWhiteSpace(pkgSettings.PackageParameters) ? packageConfig.PackageParameters : pkgSettings.PackageParameters; if (pkgSettings.ForceX86) { packageConfig.ForceX86 = true; } if (pkgSettings.AllowMultipleVersions) { packageConfig.AllowMultipleVersions = true; } if (pkgSettings.IgnoreDependencies) { packageConfig.IgnoreDependencies = true; } packageConfigs.Add(packageConfig); } } return(packageConfigs); }
/// <summary> /// Looks for file and generates a notification. /// </summary> public void look_for_file_and_generate_notification() { try { IList <string> filesToProcess = new List <string>(); if (is_directory(FilePath)) { filesToProcess = _fileSystem.get_files(FilePath, "*.*", SearchOption.AllDirectories).ToList(); } else if (_fileSystem.file_exists(FilePath)) { filesToProcess.Add(FilePath); } if (filesToProcess.Count != 0) { foreach (string file in filesToProcess) { var tempFile = file; if (_renameFile) { var renamedFile = string.Format( "{0}_renamed{1}", _fileSystem.get_file_name_without_extension(file), _fileSystem.get_file_extension(file)); tempFile = _fileSystem.combine_paths(_fileSystem.get_directory_name(file), renamedFile); _fileSystem.move_file(file, tempFile); } file_found_event.Invoke(new FileFoundEventArgs(tempFile)); } } } catch (Exception ex) { this.Log() .Error( () => string.Format("Exception caught when watching for trigger files:{0}{1}", Environment.NewLine, ex)); } }
public void set_executable_path_if_not_set() { if (!string.IsNullOrWhiteSpace(_exePath)) { return; } foreach (var location in _exeLocations) { if (_fileSystem.file_exists(location)) { _exePath = location; break; } } if (string.IsNullOrWhiteSpace(_exePath)) { throw new FileNotFoundException("Unable to find suitable location for the executable. Searched the following locations: '{0}'".format_with(string.Join("; ", _exeLocations))); } }
public string hash_file(string filePath) { if (!_fileSystem.file_exists(filePath)) { return(string.Empty); } try { var hash = _hashAlgorithm.ComputeHash(_fileSystem.read_file_bytes(filePath)); return(BitConverter.ToString(hash).Replace("-", string.Empty)); } catch (IOException ex) { this.Log().Warn(() => "Error computing hash for '{0}'{1} Captured error:{1} {2}".format_with(filePath, Environment.NewLine, ex.Message)); //IO.IO_FileTooLong2GB (over Int32.MaxValue) return(ApplicationParameters.HashProviderFileTooBig); return("UnableToDetectChanges_FileTooBig"); } }
private void test_package(VerifyPackageMessage message) { //var lockTaken = TransactionLock.acquire(VAGRANT_LOCK_NAME, 7200); //if (!lockTaken) //{ // Bootstrap.handle_exception(new ApplicationException("Testing package {0} v{1} timed out waiting on transaction lock to open".format_with(message.PackageId, message.PackageVersion))); // return; //} try { this.Log().Info(() => "========== {0} v{1} ==========".format_with(message.PackageId, message.PackageVersion)); this.Log().Info(() => "Testing Package: {0} Version: {1}".format_with(message.PackageId, message.PackageVersion)); _fileSystem.delete_file(".\\choco_logs\\chocolatey.log"); var prepSuccess = _testService.prep(); var resetSuccess = _testService.reset(); if (!prepSuccess || !resetSuccess) { Bootstrap.handle_exception(new ApplicationException("Unable to test package due to testing service issues. See log for details")); return; } this.Log().Info(() => "Checking install."); var installResults = _testService.run( "choco.exe install {0} --version {1} -fdvy --execution-timeout={2} --allow-downgrade".format_with( message.PackageId, message.PackageVersion, _configuration.CommandExecutionTimeoutSeconds)); if (had_environment_errors(installResults)) { return; } this.Log().Debug(() => "Grabbing actual log file to include in report."); var installLog = string.Empty; var installLogFile = ".\\choco_logs\\chocolatey.log"; try { if (_fileSystem.file_exists(installLogFile)) { installLog = _fileSystem.read_file(installLogFile); _fileSystem.delete_file(installLogFile); } } catch (Exception ex) { Bootstrap.handle_exception(new ApplicationException("Unable to read file '{0}':{1} {2}".format_with(installLogFile, Environment.NewLine, ex.ToString()), ex)); } this.Log().Debug(() => "Grabbing results files (.registry/.files) to include in report."); var registrySnapshot = string.Empty; var registrySnapshotFile = ".\\files\\{0}.{1}\\.registry".format_with(message.PackageId, message.PackageVersion); try { if (_fileSystem.file_exists(registrySnapshotFile)) { registrySnapshot = _fileSystem.read_file(registrySnapshotFile); } } catch (Exception ex) { Bootstrap.handle_exception(new ApplicationException("Unable to read file '{0}':{1} {2}".format_with(registrySnapshotFile, Environment.NewLine, ex.ToString()), ex)); } var filesSnapshot = string.Empty; var filesSnapshotFile = ".\\files\\{0}.{1}\\.files".format_with(message.PackageId, message.PackageVersion); try { if (_fileSystem.file_exists(filesSnapshotFile)) { filesSnapshot = _fileSystem.read_file(filesSnapshotFile); } } catch (Exception ex) { Bootstrap.handle_exception(new ApplicationException("Unable to read file '{0}':{1} {2}".format_with(filesSnapshotFile, Environment.NewLine, ex.ToString()), ex)); } var success = installResults.Success && installResults.ExitCode == 0; this.Log().Info(() => "Install was '{0}'.".format_with(success ? "successful" : "not successful")); if (detect_vagrant_errors(installResults.Logs, message.PackageId, message.PackageVersion)) { return; } var upgradeResults = new TestCommandOutputResult(); var uninstallLog = string.Empty; var uninstallResults = new TestCommandOutputResult(); if (success) { this.Log().Info(() => "Now checking uninstall."); uninstallResults = _testService.run("choco.exe uninstall {0} --version {1} -dvy --execution-timeout={2}".format_with(message.PackageId, message.PackageVersion, _configuration.CommandExecutionTimeoutSeconds)); this.Log().Info(() => "Uninstall was '{0}'.".format_with(uninstallResults.ExitCode == 0 ? "successful" : "not successful")); this.Log().Debug(() => "Grabbing actual log file to include in report."); var uninstallLogFile = ".\\choco_logs\\chocolatey.log"; try { if (_fileSystem.file_exists(uninstallLogFile)) { uninstallLog = _fileSystem.read_file(uninstallLogFile); _fileSystem.delete_file(uninstallLogFile); } } catch (Exception ex) { Bootstrap.handle_exception(new ApplicationException("Unable to read file '{0}':{1} {2}".format_with(uninstallLogFile, Environment.NewLine, ex.ToString()), ex)); } if (had_environment_errors(uninstallResults)) { return; } if (detect_vagrant_errors(uninstallResults.Logs, message.PackageId, message.PackageVersion)) { return; } } foreach (var subDirectory in _fileSystem.get_directories(".\\files").or_empty_list_if_null()) { try { _fileSystem.delete_directory_if_exists(subDirectory, recursive: true); } catch (Exception ex) { Bootstrap.handle_exception(new ApplicationException("Unable to cleanup files directory (where .chocolatey files are put):{0} {1}".format_with(Environment.NewLine, ex.ToString()), ex)); } } var logs = new List <PackageTestLog>(); var summary = new StringBuilder(); summary.AppendFormat("{0} v{1} - {2} - Package Test Results", message.PackageId, message.PackageVersion, success ? "Passed" : "Failed"); summary.AppendFormat("{0} * [{1}packages/{2}/{3}]({1}packages/{2}/{3})", Environment.NewLine, _configuration.PackagesUrl.ensure_trailing_slash(), message.PackageId, message.PackageVersion); summary.AppendFormat("{0} * Tested {1} +00:00", Environment.NewLine, DateTime.UtcNow.ToString("dd MMM yyyy HH:mm:ss")); summary.AppendFormat("{0} * Tested against {1} ({2})", Environment.NewLine, "win2012r2x64", "Windows Server 2012 R2 x64"); summary.AppendFormat("{0} * Tested with the latest version of choco, possibly a beta version.", Environment.NewLine); summary.AppendFormat( "{0} * Tested with {1} service v{2}{3}", Environment.NewLine, ApplicationParameters.Name, ApplicationParameters.ProductVersion, string.IsNullOrWhiteSpace(_configuration.InstanceName) ? string.Empty : " (Instance: {0})".format_with(_configuration.InstanceName) ); summary.AppendFormat( "{0} * Install {1}.", Environment.NewLine, installResults.ExitCode == 0 ? "was successful" : "failed. Note that the process may have hung, indicating a not completely silent install. This is usually seen when the last entry in the log is calling the install. This can also happen when a window pops up and needs to be closed to continue"); if (!string.IsNullOrWhiteSpace(upgradeResults.Logs)) { summary.AppendFormat( "{0} * Upgrade {1}.", Environment.NewLine, upgradeResults.ExitCode == 0 ? "was successful" : "failed. Note that the process may have hung, indicating a not completely silent install. This is usually seen when the last entry in the log is calling the install. This can also happen when a window pops up and needs to be closed to continue"); } if (!string.IsNullOrWhiteSpace(uninstallResults.Logs)) { summary.AppendFormat( "{0} * Uninstall {1}.", Environment.NewLine, uninstallResults.ExitCode == 0 ? "was successful" : "failed (allowed). Note that the process may have hung, indicating a not completely silent uninstall. This is usually seen when the last entry in the log is calling the uninstall. This can also happen when a window pops up and needs to be closed to continue"); } logs.Add(new PackageTestLog("_Summary.md", summary.ToString())); if (!string.IsNullOrWhiteSpace(installResults.Logs)) { logs.Add(new PackageTestLog("Install.txt", string.IsNullOrWhiteSpace(installLog) ? installResults.Logs : installLog)); } if (!string.IsNullOrWhiteSpace(registrySnapshot)) { logs.Add(new PackageTestLog("1.RegistrySnapshot.xml", registrySnapshot)); } if (!string.IsNullOrWhiteSpace(filesSnapshot)) { logs.Add(new PackageTestLog("FilesSnapshot.xml", filesSnapshot)); } if (!string.IsNullOrWhiteSpace(upgradeResults.Logs)) { logs.Add(new PackageTestLog("Upgrade.txt", upgradeResults.Logs)); } if (!string.IsNullOrWhiteSpace(uninstallResults.Logs)) { logs.Add(new PackageTestLog("Uninstall.txt", string.IsNullOrWhiteSpace(uninstallLog) ? uninstallResults.Logs : uninstallLog)); } EventManager.publish( new PackageTestResultMessage( message.PackageId, message.PackageVersion, "Windows2012R2 x64", "win2012r2x64", DateTime.UtcNow, logs, success: success )); } catch (Exception ex) { Bootstrap.handle_exception(ex); } //finally //{ // TransactionLock.release(VAGRANT_LOCK_NAME, lockTaken: true); //} }
public void remove(RegistryApplicationKey key, ChocolateyConfiguration config, PackageResult packageResult, string packageCacheLocation) { this.Log().Debug(() => " Preparing uninstall key '{0}'".format_with(key.UninstallString.to_string().escape_curly_braces())); if ((!string.IsNullOrWhiteSpace(key.InstallLocation) && !_fileSystem.directory_exists(key.InstallLocation)) || !_registryService.installer_value_exists(key.KeyPath, ApplicationParameters.RegistryValueInstallLocation)) { this.Log().Info(" Skipping auto uninstaller - The application appears to have been uninstalled already by other means."); this.Log().Debug(() => " Searched for install path '{0}' - found? {1}".format_with(key.InstallLocation.to_string().escape_curly_braces(), _fileSystem.directory_exists(key.InstallLocation))); this.Log().Debug(() => " Searched for registry key '{0}' value '{1}' - found? {2}".format_with(key.KeyPath.escape_curly_braces(), ApplicationParameters.RegistryValueInstallLocation, _registryService.installer_value_exists(key.KeyPath, ApplicationParameters.RegistryValueInstallLocation))); return; } // split on " /" and " -" for quite a bit more accuracy IList <string> uninstallArgsSplit = key.UninstallString.to_string().Split(new[] { " /", " -" }, StringSplitOptions.RemoveEmptyEntries).ToList(); var uninstallExe = uninstallArgsSplit.DefaultIfEmpty(string.Empty).FirstOrDefault(); if (uninstallExe.Count(u => u == '"') > 2) { uninstallExe = uninstallExe.Split(new [] { " \"" }, StringSplitOptions.RemoveEmptyEntries).First(); } var uninstallArgs = key.UninstallString.to_string().Replace(uninstallExe.to_string(), string.Empty); uninstallExe = uninstallExe.remove_surrounding_quotes(); this.Log().Debug(() => " Uninstaller path is '{0}'".format_with(uninstallExe)); if (uninstallExe.contains("\\") || uninstallExe.contains("/")) { if (!_fileSystem.file_exists(uninstallExe)) { this.Log().Info(" Skipping auto uninstaller - The uninstaller file no longer exists. \"{0}\"".format_with(uninstallExe)); return; } } IInstaller installer = get_installer_type(key, uninstallExe, uninstallArgs); this.Log().Debug(() => " Installer type is '{0}'".format_with(installer.GetType().Name)); if (key.InstallerType == InstallerType.Msi) { // because sometimes the key is set with /i to allow for modify :/ uninstallArgs = uninstallArgs.Replace("/I{", "/X{"); uninstallArgs = uninstallArgs.Replace("/i{", "/X{"); uninstallArgs = uninstallArgs.Replace("/I ", "/X "); uninstallArgs = uninstallArgs.Replace("/i ", "/X "); } if (!key.HasQuietUninstall) { //todo: ultimately we should merge keys uninstallArgs += " " + installer.build_uninstall_command_arguments(); } this.Log().Debug(() => " Setting up uninstall logging directory at {0}".format_with(packageCacheLocation.escape_curly_braces())); _fileSystem.create_directory_if_not_exists(_fileSystem.get_directory_name(packageCacheLocation)); uninstallArgs = uninstallArgs.Replace(InstallTokens.PACKAGE_LOCATION, packageCacheLocation); uninstallArgs = uninstallArgs.Replace(InstallTokens.TEMP_LOCATION, packageCacheLocation); this.Log().Debug(() => " Args are '{0}'".format_with(uninstallArgs.escape_curly_braces())); if (!key.HasQuietUninstall && installer.GetType() == typeof(CustomInstaller)) { if (!config.Information.IsLicensedVersion) { this.Log().Warn(@" Did you know licensed versions of Chocolatey are 95% effective with Automatic Uninstaller due to licensed enhancements and Package Synchronizer? "); } var skipUninstaller = true; var timeout = config.PromptForConfirmation ? 0 : 30; var selection = InteractivePrompt.prompt_for_confirmation( "Uninstall may not be silent (could not detect). Proceed?", new[] { "yes", "no" }, defaultChoice: "no", requireAnswer: true, allowShortAnswer: true, shortPrompt: true, timeoutInSeconds: timeout ); if (selection.is_equal_to("yes")) { skipUninstaller = false; } if (skipUninstaller) { this.Log().Info(" Skipping auto uninstaller - Installer type was not detected and no silent uninstall key exists."); this.Log().Warn("If the application was not removed with a chocolateyUninstall.ps1,{0} please remove it from Programs and Features manually.".format_with(Environment.NewLine)); return; } } var exitCode = _commandExecutor.execute( uninstallExe, uninstallArgs.trim_safe(), config.CommandExecutionTimeoutSeconds, (s, e) => { if (e == null || string.IsNullOrWhiteSpace(e.Data)) { return; } this.Log().Info(() => " [AutoUninstaller] {0}".format_with(e.Data.escape_curly_braces())); }, (s, e) => { if (e == null || string.IsNullOrWhiteSpace(e.Data)) { return; } this.Log().Error(() => " [AutoUninstaller] {0}".format_with(e.Data.escape_curly_braces())); }, updateProcessPath: false); if (!installer.ValidUninstallExitCodes.Contains(exitCode)) { Environment.ExitCode = exitCode; string logMessage = " Auto uninstaller failed. Please remove machine installation manually.{0} Exit code was {1}".format_with(Environment.NewLine, exitCode); this.Log().Error(() => logMessage.escape_curly_braces()); packageResult.Messages.Add(new ResultMessage(config.Features.FailOnAutoUninstaller ? ResultType.Error : ResultType.Warn, logMessage)); } else { this.Log().Info(() => " Auto uninstaller has successfully uninstalled {0} or detected previous uninstall.".format_with(packageResult.Package.Id)); } }
public void run(ChocolateyConfiguration configuration) { var packageResults = _nugetService.get_all_installed_packages(configuration); var settings = new XmlWriterSettings { Indent = true, Encoding = new UTF8Encoding(false) }; FaultTolerance.try_catch_with_logging_exception( () => { using (var stringWriter = new StringWriter()) { using (var xw = XmlWriter.Create(stringWriter, settings)) { xw.WriteProcessingInstruction("xml", "version=\"1.0\" encoding=\"utf-8\""); xw.WriteStartElement("packages"); foreach (var packageResult in packageResults) { xw.WriteStartElement("package"); xw.WriteAttributeString("id", packageResult.Package.Id); if (configuration.ExportCommand.IncludeVersionNumbers) { xw.WriteAttributeString("version", packageResult.Package.Version.ToString()); } xw.WriteEndElement(); } xw.WriteEndElement(); xw.Flush(); } var fullOutputFilePath = _fileSystem.get_full_path(configuration.ExportCommand.OutputFilePath); var fileExists = _fileSystem.file_exists(fullOutputFilePath); // If the file doesn't already exist, just write the new one out directly if (!fileExists) { _fileSystem.write_file( fullOutputFilePath, stringWriter.GetStringBuilder().ToString(), new UTF8Encoding(false)); return; } // Otherwise, create an update file, and resiliently move it into place. var tempUpdateFile = fullOutputFilePath + "." + Process.GetCurrentProcess().Id + ".update"; _fileSystem.write_file(tempUpdateFile, stringWriter.GetStringBuilder().ToString(), new UTF8Encoding(false)); _fileSystem.replace_file(tempUpdateFile, fullOutputFilePath, fullOutputFilePath + ".backup"); } }, errorMessage: "Error exporting currently installed packages", throwError: true ); }
public void run(PackageResult packageResult, ChocolateyConfiguration config) { var installDirectory = packageResult != null ? packageResult.InstallLocation : string.Empty; if (string.IsNullOrWhiteSpace(installDirectory) || installDirectory.is_equal_to(ApplicationParameters.InstallLocation) || installDirectory.is_equal_to(ApplicationParameters.PackagesLocation)) { var logMessage = "Install location is not specific enough, cannot capture files:{0} Erroneous install location captured as '{1}'".format_with(Environment.NewLine, installDirectory); if (packageResult != null) { packageResult.Messages.Add(new ResultMessage(ResultType.Warn, logMessage)); } this.Log().Error(logMessage); return; } var transformFiles = _fileSystem.get_files(installDirectory, "*" + ApplicationParameters.ConfigFileTransformExtension, SearchOption.AllDirectories); foreach (var transformFile in transformFiles.or_empty_list_if_null()) { this.Log().Debug(() => "Preparing transform for '{0}'".format_with(transformFile)); var targetFileName = _fileSystem.get_file_name(transformFile.Replace(ApplicationParameters.ConfigFileTransformExtension, string.Empty)); // target files must exist, otherwise one is added next to the transform var targetFiles = _fileSystem.get_files(installDirectory, targetFileName, SearchOption.AllDirectories); var targetFilesTest = targetFiles as IList <string> ?? targetFiles.ToList(); if (!targetFilesTest.Any()) { targetFiles = new[] { transformFile.Replace(ApplicationParameters.ConfigFileTransformExtension, string.Empty) }; this.Log().Debug(() => "No matching files found for transform {0}.{1} Creating '{2}'".format_with(_fileSystem.get_file_name(transformFile), Environment.NewLine, targetFiles.FirstOrDefault())); } foreach (var targetFile in targetFilesTest.or_empty_list_if_null()) { GlobalMutex.enter( () => { var backupTargetFile = targetFile.Replace(ApplicationParameters.PackagesLocation, ApplicationParameters.PackageBackupLocation); FaultTolerance.try_catch_with_logging_exception( () => { // if there is a backup, we need to put it back in place // the user has indicated they are using transforms by putting // the transform file into the folder, so we will override // the replacement of the file and instead pull from the last // backup and let the transform to its thing instead. if (_fileSystem.file_exists(backupTargetFile)) { this.Log().Debug(() => "Restoring backup configuration file for '{0}'.".format_with(targetFile)); _fileSystem.copy_file(backupTargetFile, targetFile, overwriteExisting: true); } }, "Error replacing backup config file", throwError: false, logWarningInsteadOfError: true); try { this.Log().Info(() => "Transforming '{0}' with the data from '{1}'".format_with(_fileSystem.get_file_name(targetFile), _fileSystem.get_file_name(transformFile))); using (var transformation = new XmlTransformation(_fileSystem.read_file(transformFile), isTransformAFile: false, logger: null)) { using (var document = new XmlTransformableDocument { PreserveWhitespace = true }) { using (var inputStream = _fileSystem.open_file_readonly(targetFile)) { document.Load(inputStream); } // before applying the XDT transformation, let's make a // backup of the file that should be transformed, in case // things don't go correctly this.Log().Debug(() => "Creating backup configuration file for '{0}'.".format_with(targetFile)); _fileSystem.copy_file(targetFile, backupTargetFile, overwriteExisting: true); bool succeeded = transformation.Apply(document); if (succeeded) { this.Log().Debug(() => "Transform applied successfully for '{0}'".format_with(targetFile)); using (var memoryStream = new MemoryStream()) { document.Save(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); using (var fileStream = _fileSystem.create_file(targetFile)) { fileStream.SetLength(0); memoryStream.CopyTo(fileStream); } } // need to test that the transformed configuration file is valid // XML. We can test this by trying to load it again into an XML document try { this.Log().Debug(() => "Verifying transformed configuration file..."); document.Load(targetFile); this.Log().Debug(() => "Transformed configuration file verified."); } catch (Exception) { this.Log().Warn(() => "Transformed configuration file doesn't contain valid XML. Restoring backup file..."); _fileSystem.copy_file(backupTargetFile, targetFile, overwriteExisting: true); this.Log().Debug(() => "Backup file restored."); } } else { // at this point, there is no need to restore the backup file, // as the resulting transform hasn't actually been written to disk. this.Log().Warn(() => "Transform failed for '{0}'".format_with(targetFile)); } } } } catch (Exception) { FaultTolerance.try_catch_with_logging_exception( () => { // something went wrong with the transformation, so we should restore // the original configuration file from the backup this.Log().Warn(() => "There was a problem transforming configuration file, restoring backup file..."); _fileSystem.copy_file(backupTargetFile, targetFile, overwriteExisting: true); this.Log().Debug(() => "Backup file restored."); }, "Error restoring backup configuration file."); } }, MUTEX_TIMEOUT); } } }
public void install(ChocolateyConfiguration configuration, PackageResult packageResult) { _fileSystem.create_directory_if_not_exists(ApplicationParameters.ShimsLocation); if (packageResult.InstallLocation.is_equal_to(ApplicationParameters.InstallLocation) || packageResult.InstallLocation.is_equal_to(ApplicationParameters.PackagesLocation)) { var logMessage = "Install location is not specific enough, cannot run shimgen:{0} Erroneous install location captured as '{1}'".format_with(Environment.NewLine, packageResult.InstallLocation); packageResult.Messages.Add(new ResultMessage(ResultType.Warn, logMessage)); this.Log().Error(logMessage); return; } //gather all .exes in the folder var exeFiles = _fileSystem.get_files(packageResult.InstallLocation, pattern: "*.exe", option: SearchOption.AllDirectories); foreach (string file in exeFiles.or_empty_list_if_null()) { if (_fileSystem.file_exists(file + ".ignore")) { continue; } bool isGui = _fileSystem.file_exists(file + ".gui"); //todo: v2 be able to determine gui automatically var args = ExternalCommandArgsBuilder.build_arguments(configuration, _shimGenArguments); var shimLocation = _fileSystem.combine_paths(ApplicationParameters.ShimsLocation, _fileSystem.get_file_name(file)); var argsForPackage = args.Replace(PATH_TOKEN, file.Replace(ApplicationParameters.InstallLocation, "..\\")).Replace(OUTPUT_TOKEN, shimLocation).Replace(ICON_PATH_TOKEN, file); if (isGui) { argsForPackage += " --gui"; } var exitCode = _commandExecutor.execute( _shimGenExePath, argsForPackage, configuration.CommandExecutionTimeoutSeconds, (s, e) => { if (string.IsNullOrWhiteSpace(e.Data)) { return; } this.Log().Debug(() => " [ShimGen] {0}".format_with(e.Data)); }, (s, e) => { if (string.IsNullOrWhiteSpace(e.Data)) { return; } this.Log().Error(() => " [ShimGen] {0}".format_with(e.Data)); }, updateProcessPath: true ); if (exitCode != 0) { Environment.ExitCode = exitCode; } else { this.Log().Info(() => " ShimGen has successfully created a {0}shim for {1}".format_with(isGui ? "gui " : string.Empty, _fileSystem.get_file_name(file))); this.Log().Debug(() => " Created: {0}{1} Targeting: {2}{1} IsGui:{3}{1}".format_with(shimLocation, Environment.NewLine, file, isGui)); } } }
private void test_package(VerifyPackageMessage message) { //var lockTaken = TransactionLock.acquire(VAGRANT_LOCK_NAME, 7200); //if (!lockTaken) //{ // Bootstrap.handle_exception(new ApplicationException("Testing package {0} v{1} timed out waiting on transaction lock to open".format_with(message.PackageId, message.PackageVersion))); // return; //} try { this.Log().Info(() => "========== {0} v{1} ==========".format_with(message.PackageId, message.PackageVersion)); this.Log().Info(() => "Testing Package: {0} Version: {1}".format_with(message.PackageId, message.PackageVersion)); _fileSystem.delete_file(".\\choco_logs\\chocolatey.log"); var prepSuccess = _testService.prep(); var resetSuccess = _testService.reset(); if (!prepSuccess || !resetSuccess) { Bootstrap.handle_exception(new ApplicationException("Unable to test package due to testing service issues. See log for details")); return; } if (_fileSystem.file_exists(_configuration.VboxIdPath)) { _vmId = _fileSystem.read_file(_configuration.VboxIdPath); _vmIdAvailable = !string.IsNullOrWhiteSpace(_vmId); } var tempFolder = Environment.GetEnvironmentVariable("TEMP"); if (_vmIdAvailable && !tempFolder.EndsWith(_vmId)) { var runFolder = "{0}\\{1}".format_with(tempFolder, _vmId); this.Log().Info(() => "Setting temp folder to: {0}".format_with(runFolder)); Environment.SetEnvironmentVariable("TEMP", runFolder); _fileSystem.create_directory_if_not_exists(runFolder); } this.Log().Info(() => "Checking install."); const string imageDirectory = ".\\images"; _fileSystem.create_directory_if_not_exists(imageDirectory); var installImage = string.Empty; var installResults = _testService.run( "choco.exe install {0} --version {1} -fdvy --execution-timeout={2} --allow-downgrade".format_with( message.PackageId, message.PackageVersion, _configuration.CommandExecutionTimeoutSeconds), () => { this.Log().Info(() => "Timeout triggered."); if (string.IsNullOrWhiteSpace(_vboxManageExe) || string.IsNullOrWhiteSpace(_configuration.VboxIdPath)) { return; } if (!_vmIdAvailable) { return; } var imageLocation = _fileSystem.combine_paths(imageDirectory, _imageFormat.format_with( message.PackageId, message.PackageVersion, DateTime.Now.ToString(_dateTimeFormat), "install" )); try { CommandExecutor.execute_static(_vboxManageExe, "controlvm {" + _vmId + "} screenshotpng " + imageLocation, 30, _fileSystem.get_directory_name(Assembly.GetExecutingAssembly().Location), (o, e) => { if (e == null || string.IsNullOrWhiteSpace(e.Data)) { return; } this.Log().Debug(() => " [VboxManage] {0}".format_with(e.Data)); }, (o, e) => { if (e == null || string.IsNullOrWhiteSpace(e.Data)) { return; } this.Log().Warn(() => " [VboxManage][Error] {0}".format_with(e.Data)); }, null, updateProcessPath: false, allowUseWindow: false); if (_fileSystem.file_exists(imageLocation)) { installImage = _imageUploadService.upload_image(imageLocation); } } catch (Exception ex) { this.Log().Warn("Image capture failed for {0}v{1}:{2} {3}".format_with(message.PackageId, message.PackageVersion, Environment.NewLine, ex.Message)); } }); installResults.ImageLink = installImage; if (had_environment_errors(installResults)) { return; } this.Log().Debug(() => "Grabbing actual log file to include in report."); var installLog = string.Empty; var installLogFile = ".\\choco_logs\\chocolatey.log"; try { if (_fileSystem.file_exists(installLogFile)) { installLog = _fileSystem.read_file(installLogFile); _fileSystem.delete_file(installLogFile); } } catch (Exception ex) { Bootstrap.handle_exception(new ApplicationException("Unable to read file '{0}':{1} {2}".format_with(installLogFile, Environment.NewLine, ex.ToString()), ex)); } this.Log().Debug(() => "Grabbing results files (.registry/.files) to include in report."); var registrySnapshot = string.Empty; var registrySnapshotFile = ".\\files\\{0}.{1}\\.registry".format_with(message.PackageId, message.PackageVersion); try { if (_fileSystem.file_exists(registrySnapshotFile)) { registrySnapshot = _fileSystem.read_file(registrySnapshotFile); } } catch (Exception ex) { Bootstrap.handle_exception(new ApplicationException("Unable to read file '{0}':{1} {2}".format_with(registrySnapshotFile, Environment.NewLine, ex.ToString()), ex)); } var filesSnapshot = string.Empty; var filesSnapshotFile = ".\\files\\{0}.{1}\\.files".format_with(message.PackageId, message.PackageVersion); try { if (_fileSystem.file_exists(filesSnapshotFile)) { filesSnapshot = _fileSystem.read_file(filesSnapshotFile); } } catch (Exception ex) { Bootstrap.handle_exception(new ApplicationException("Unable to read file '{0}':{1} {2}".format_with(filesSnapshotFile, Environment.NewLine, ex.ToString()), ex)); } var success = installResults.Success && installResults.ExitCode == 0; this.Log().Info(() => "Install was '{0}'.".format_with(success ? "successful" : "not successful")); if (detect_vagrant_errors(installResults.Logs, message.PackageId, message.PackageVersion)) { return; } var upgradeResults = new TestCommandOutputResult(); var uninstallLog = string.Empty; var uninstallResults = new TestCommandOutputResult(); if (success) { this.Log().Info(() => "Now checking uninstall."); var uninstallImage = string.Empty; uninstallResults = _testService.run("choco.exe uninstall {0} --version {1} -dvy --execution-timeout={2}".format_with(message.PackageId, message.PackageVersion, _configuration.CommandExecutionTimeoutSeconds), () => { if (string.IsNullOrWhiteSpace(_vboxManageExe) || string.IsNullOrWhiteSpace(_configuration.VboxIdPath)) { return; } if (!_fileSystem.file_exists(_configuration.VboxIdPath)) { return; } if (!_vmIdAvailable) { return; } var imageLocation = _fileSystem.combine_paths(imageDirectory, _imageFormat.format_with( message.PackageId, message.PackageVersion, DateTime.Now.ToString(_dateTimeFormat), "uninstall" )); try { CommandExecutor.execute_static(_vboxManageExe, "controlvm {" + _vmId + "} screenshotpng " + imageLocation, 30, _fileSystem.get_directory_name(Assembly.GetExecutingAssembly().Location), (o, e) => { if (e == null || string.IsNullOrWhiteSpace(e.Data)) { return; } this.Log().Debug(() => " [VboxManage] {0}".format_with(e.Data)); }, (o, e) => { if (e == null || string.IsNullOrWhiteSpace(e.Data)) { return; } this.Log().Warn(() => " [VboxManage][Error] {0}".format_with(e.Data)); }, null, updateProcessPath: false, allowUseWindow: false); if (_fileSystem.file_exists(imageLocation)) { uninstallImage = _imageUploadService.upload_image(imageLocation); } } catch (Exception ex) { this.Log().Warn("Image capture failed for {0}v{1}:{2} {3}".format_with(message.PackageId, message.PackageVersion, Environment.NewLine, ex.Message)); } }); this.Log().Info(() => "Uninstall was '{0}'.".format_with(uninstallResults.ExitCode == 0 ? "successful" : "not successful")); this.Log().Debug(() => "Grabbing actual log file to include in report."); uninstallResults.ImageLink = uninstallImage; var uninstallLogFile = ".\\choco_logs\\chocolatey.log"; try { if (_fileSystem.file_exists(uninstallLogFile)) { uninstallLog = _fileSystem.read_file(uninstallLogFile); _fileSystem.delete_file(uninstallLogFile); } } catch (Exception ex) { Bootstrap.handle_exception(new ApplicationException("Unable to read file '{0}':{1} {2}".format_with(uninstallLogFile, Environment.NewLine, ex.ToString()), ex)); } if (had_environment_errors(uninstallResults)) { return; } if (detect_vagrant_errors(uninstallResults.Logs, message.PackageId, message.PackageVersion)) { return; } } foreach (var subDirectory in _fileSystem.get_directories(".\\files").or_empty_list_if_null()) { try { _fileSystem.delete_directory_if_exists(subDirectory, recursive: true); } catch (Exception ex) { Bootstrap.handle_exception(new ApplicationException("Unable to cleanup files directory (where .chocolatey files are put):{0} {1}".format_with(Environment.NewLine, ex.ToString()), ex)); } } var logs = new List <PackageTestLog>(); var summary = new StringBuilder(); summary.AppendFormat("{0} v{1} - {2} - Package Test Results", message.PackageId, message.PackageVersion, success ? "Passed" : "Failed"); summary.AppendFormat("{0} * [{1}packages/{2}/{3}]({1}packages/{2}/{3})", Environment.NewLine, _configuration.PackagesUrl.ensure_trailing_slash(), message.PackageId, message.PackageVersion); summary.AppendFormat("{0} * Tested {1} +00:00", Environment.NewLine, DateTime.UtcNow.ToString("dd MMM yyyy HH:mm:ss")); summary.AppendFormat("{0} * Tested against {1} ({2})", Environment.NewLine, "win2012r2x64", "Windows Server 2012 R2 x64"); summary.AppendFormat("{0} * Tested with the latest version of choco, possibly a beta version.", Environment.NewLine); summary.AppendFormat( "{0} * Tested with {1} service v{2}{3}", Environment.NewLine, ApplicationParameters.Name, ApplicationParameters.ProductVersion, string.IsNullOrWhiteSpace(_configuration.InstanceName) ? string.Empty : " (Instance: {0})".format_with(_configuration.InstanceName) ); summary.AppendFormat( "{0} * Install {1}.", Environment.NewLine, installResults.ExitCode == 0 ? "was successful" : "failed. Note that the process may have hung, indicating a not completely silent install. This is usually seen when the last entry in the log is calling the install. This can also happen when a window pops up and needs to be closed to continue"); if (!string.IsNullOrWhiteSpace(upgradeResults.Logs)) { summary.AppendFormat( "{0} * Upgrade {1}.", Environment.NewLine, upgradeResults.ExitCode == 0 ? "was successful" : "failed. Note that the process may have hung, indicating a not completely silent install. This is usually seen when the last entry in the log is calling the install. This can also happen when a window pops up and needs to be closed to continue"); } if (!string.IsNullOrWhiteSpace(uninstallResults.Logs)) { summary.AppendFormat( "{0} * Uninstall {1}.", Environment.NewLine, uninstallResults.ExitCode == 0 ? "was successful" : "failed (allowed). Note that the process may have hung, indicating a not completely silent uninstall. This is usually seen when the last entry in the log is calling the uninstall. This can also happen when a window pops up and needs to be closed to continue"); } logs.Add(new PackageTestLog("_Summary.md", summary.ToString())); if (!string.IsNullOrWhiteSpace(installResults.Logs)) { logs.Add(new PackageTestLog("Install.txt", string.IsNullOrWhiteSpace(installLog) ? installResults.Logs : installLog)); } if (!string.IsNullOrWhiteSpace(installResults.ImageLink)) { logs.Add(new PackageTestLog("InstallImage.md", @" This is the image that was taken when the install test failed: ![{0} v{1} install failure]({2}) ".format_with(message.PackageId, message.PackageVersion, installResults.ImageLink))); } if (!string.IsNullOrWhiteSpace(registrySnapshot)) { logs.Add(new PackageTestLog("1.RegistrySnapshot.xml", registrySnapshot)); } if (!string.IsNullOrWhiteSpace(filesSnapshot)) { logs.Add(new PackageTestLog("FilesSnapshot.xml", filesSnapshot)); } if (!string.IsNullOrWhiteSpace(upgradeResults.Logs)) { logs.Add(new PackageTestLog("Upgrade.txt", upgradeResults.Logs)); } if (!string.IsNullOrWhiteSpace(uninstallResults.Logs)) { logs.Add(new PackageTestLog("Uninstall.txt", string.IsNullOrWhiteSpace(uninstallLog) ? uninstallResults.Logs : uninstallLog)); } if (!string.IsNullOrWhiteSpace(uninstallResults.ImageLink)) { logs.Add(new PackageTestLog("UninstallImage.md", @" This is the image that was taken when the uninstall test failed: ![{0} v{1} uninstall failure]({2}) ".format_with(message.PackageId, message.PackageVersion, uninstallResults.ImageLink))); } EventManager.publish( new PackageTestResultMessage( message.PackageId, message.PackageVersion, "Windows2012R2 x64", "win2012r2x64", DateTime.UtcNow, logs, success: success )); } catch (Exception ex) { Bootstrap.handle_exception(ex); } //finally //{ // TransactionLock.release(VAGRANT_LOCK_NAME, lockTaken: true); //} }
//// http://stackoverflow.com/a/8861895/18475 //// http://stackoverflow.com/a/2864714/18475 //[DllImport("kernel32.dll", SetLastError = true)] //private static extern bool SetDllDirectory(string lpPathName); //public struct DieInternal //{ // [SuppressUnmanagedCodeSecurity] // [DllImport("diedll", CallingConvention = CallingConvention.StdCall, EntryPoint = "_DIE_scanExW@20", SetLastError = true)] // internal static extern int scanExW_0([MarshalAs(UnmanagedType.LPWStr)] string pwszFileName, sbyte[] pszOutBuffer, int nOutBufferSize, uint nFlags, [MarshalAs(UnmanagedType.LPWStr)] string pwszDataBase); //} //public string scan_file(string filePath) //{ // if (Platform.get_platform() != PlatformType.Windows) // { // this.Log().Debug("Unable to detect file types when not on Windows"); // return string.Empty; // } // try // { // var successPath = SetDllDirectory(dieDllLocation); // if (!successPath) // { // "chocolatey".Log().Warn("Error during native SetDllDirectory call - {0}".format_with(Marshal.GetLastWin32Error())); // } // var outputBuffer = new sbyte[1024]; // int outputBufferSize = outputBuffer.Length; // const uint flags = DIE_SINGLELINEOUTPUT; // var success = DieInternal.scanExW_0(filePath, outputBuffer, outputBufferSize, flags, databaseLocation); // if (success != 0) // { // "chocolatey".Log().Warn("Error during native _DIE_scanExW call - {0}".format_with(Marshal.GetLastWin32Error())); // } // byte[] outputBytes = Array.ConvertAll(outputBuffer, (a) => (byte)a); // var output = Encoding.UTF8.GetString(outputBytes).to_string().Trim('\0'); // return output; // } // catch (Exception ex) // { // this.Log().Warn("Unable to detect type for '{0}':{1} {2}".format_with(_fileSystem.get_file_name(filePath), Environment.NewLine, ex.Message)); // return string.Empty; // } //} public string scan_file(string filePath) { if (Platform.get_platform() != PlatformType.Windows) { this.Log().Debug("Unable to detect file types when not on Windows"); return(string.Empty); } // http://stackoverflow.com/q/5503951/18475 // http://stackoverflow.com/a/10852827/18475 // http://scottbilas.com/blog/automatically-choose-32-or-64-bit-mixed-mode-dlls/ //todo: convert this to call the exe assembly instead. The dll is 32bit and won't work with AnyCPU filePath = _fileSystem.get_full_path(filePath); var dieDllLocation = _fileSystem.combine_paths(ApplicationParameters.InstallLocation, "tools", "detector"); var diecPath = _fileSystem.combine_paths(ApplicationParameters.InstallLocation, "tools", "detector", "diec.exe"); var databaseLocation = _fileSystem.get_full_path(_fileSystem.combine_paths(ApplicationParameters.InstallLocation, "tools", "detector", "db")); this.Log().Debug("Attempting to detect type for '{0}' with db '{1}'".format_with(_fileSystem.get_file_name(filePath), databaseLocation)); if (!_fileSystem.directory_exists(diecPath) || !_fileSystem.directory_exists(databaseLocation)) { var dieZipLocation = _fileSystem.combine_paths(ApplicationParameters.InstallLocation, "tools", "detector.zip"); unzip_die_files(dieZipLocation, dieDllLocation); // finish unpacking Thread.Sleep(1000); } if (!_fileSystem.file_exists(filePath)) { this.Log().Warn("File not found at '{0}'. Unable to detect type for inexistent file.".format_with(filePath)); return(string.Empty); } try { //todo: detector databaselocation fails now - it's based on the current directory relative path //C:\\ProgramData\\chocolatey\\tools\\detector\\db var output = string.Empty; // var success = CommandExecutor.execute_static(diecPath, "\"{0}\" -singlelineoutput:yes -showoptions:no -showversion:no -database:\"{1}\"".format_with(filePath, databaseLocation), var success = CommandExecutor.execute_static(diecPath, "\"{0}\"".format_with(filePath), 60, _fileSystem.get_current_directory(), (s, e) => { if (!string.IsNullOrWhiteSpace(e.Data)) { output = e.Data; } }, (s, e) => { this.Log().Warn("{0}".format_with(e.Data)); }, false, false); return(output); } catch (Exception ex) { this.Log().Warn("Unable to detect type for '{0}':{1} {2}".format_with(_fileSystem.get_file_name(filePath), Environment.NewLine, ex.Message)); return(string.Empty); } }
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)); }
public void remove(RegistryApplicationKey key, ChocolateyConfiguration config, PackageResult packageResult, string packageCacheLocation) { var userProvidedUninstallArguments = string.Empty; var userOverrideUninstallArguments = false; var package = packageResult.Package; if (package != null) { if (!PackageUtility.package_is_a_dependency(config, package.Id) || config.ApplyInstallArgumentsToDependencies) { userProvidedUninstallArguments = config.InstallArguments; userOverrideUninstallArguments = config.OverrideArguments; if (!string.IsNullOrWhiteSpace(userProvidedUninstallArguments)) { this.Log().Debug(ChocolateyLoggers.Verbose, " Using user passed {2}uninstaller args for {0}:'{1}'".format_with(package.Id, userProvidedUninstallArguments.escape_curly_braces(), userOverrideUninstallArguments ? "overriding " : string.Empty)); } } } //todo: if there is a local package, look to use it in the future if (string.IsNullOrWhiteSpace(key.UninstallString)) { this.Log().Info(" Skipping auto uninstaller - '{0}' does not have an uninstall string.".format_with(!string.IsNullOrEmpty(key.DisplayName.to_string()) ? key.DisplayName.to_string().escape_curly_braces() : "The application")); return; } this.Log().Debug(() => " Preparing uninstall key '{0}' for '{1}'".format_with(key.UninstallString.to_string().escape_curly_braces(), key.DisplayName.to_string().escape_curly_braces())); if ((!string.IsNullOrWhiteSpace(key.InstallLocation) && !_fileSystem.directory_exists(key.InstallLocation)) || !_registryService.installer_value_exists(key.KeyPath, ApplicationParameters.RegistryValueInstallLocation)) { this.Log().Info(" Skipping auto uninstaller - '{0}' appears to have been uninstalled already by other means.".format_with(!string.IsNullOrEmpty(key.DisplayName.to_string()) ? key.DisplayName.to_string().escape_curly_braces() : "The application")); this.Log().Debug(() => " Searched for install path '{0}' - found? {1}".format_with(key.InstallLocation.to_string().escape_curly_braces(), _fileSystem.directory_exists(key.InstallLocation))); this.Log().Debug(() => " Searched for registry key '{0}' value '{1}' - found? {2}".format_with(key.KeyPath.escape_curly_braces(), ApplicationParameters.RegistryValueInstallLocation, _registryService.installer_value_exists(key.KeyPath, ApplicationParameters.RegistryValueInstallLocation))); return; } // split on " /" and " -" for quite a bit more accuracy IList <string> uninstallArgsSplit = key.UninstallString.to_string().Replace(""", "\"").Replace("'", "'").Split(new[] { " /", " -" }, StringSplitOptions.RemoveEmptyEntries).ToList(); var uninstallExe = uninstallArgsSplit.DefaultIfEmpty(string.Empty).FirstOrDefault().trim_safe(); if (uninstallExe.Count(u => u == '"') > 2) { uninstallExe = uninstallExe.Split(new [] { " \"" }, StringSplitOptions.RemoveEmptyEntries).First(); } if (uninstallExe.Count(u => u == ':') > 1) { try { var firstMatch = Regex.Match(uninstallExe, @"\s+\w\:", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); uninstallExe = uninstallExe.Substring(0, firstMatch.Index); } catch (Exception ex) { this.Log().Debug("Error splitting the uninstall string:{0} {1}".format_with(Environment.NewLine, ex.to_string())); } } var uninstallArgs = key.UninstallString.to_string().Replace(""", "\"").Replace("'", "'").Replace(uninstallExe.to_string(), string.Empty).trim_safe(); uninstallExe = uninstallExe.remove_surrounding_quotes(); this.Log().Debug(() => " Uninstaller path is '{0}'".format_with(uninstallExe)); if (uninstallExe.contains("\\") || uninstallExe.contains("/")) { if (!_fileSystem.file_exists(uninstallExe)) { this.Log().Info(" Skipping auto uninstaller - The uninstaller file no longer exists. \"{0}\"".format_with(uninstallExe)); return; } } IInstaller installer = get_installer_type(key, uninstallExe, uninstallArgs); this.Log().Debug(() => " Installer type is '{0}'".format_with(installer.GetType().Name)); if (key.InstallerType == InstallerType.Msi) { // because sometimes the key is set with /i to allow for modify :/ uninstallArgs = uninstallArgs.Replace("/I{", "/X{"); uninstallArgs = uninstallArgs.Replace("/i{", "/X{"); uninstallArgs = uninstallArgs.Replace("/I ", "/X "); uninstallArgs = uninstallArgs.Replace("/i ", "/X "); } if (!key.HasQuietUninstall) { //todo: ultimately we should merge keys uninstallArgs += " " + installer.build_uninstall_command_arguments(); } if (!string.IsNullOrWhiteSpace(userProvidedUninstallArguments)) { if (userOverrideUninstallArguments) { this.Log().Debug(() => " Replacing original uninstall arguments of '{0}' with '{1}'".format_with(uninstallArgs.escape_curly_braces(), userProvidedUninstallArguments.escape_curly_braces())); uninstallArgs = userProvidedUninstallArguments; } else { this.Log().Debug(() => " Appending original uninstall arguments with '{0}'".format_with(userProvidedUninstallArguments.escape_curly_braces())); uninstallArgs += " " + userProvidedUninstallArguments; } } this.Log().Debug(() => " Setting up uninstall logging directory at {0}".format_with(packageCacheLocation.escape_curly_braces())); _fileSystem.create_directory_if_not_exists(_fileSystem.get_directory_name(packageCacheLocation)); uninstallArgs = uninstallArgs.Replace(InstallTokens.PACKAGE_LOCATION, packageCacheLocation); uninstallArgs = uninstallArgs.Replace(InstallTokens.TEMP_LOCATION, packageCacheLocation); this.Log().Debug(() => " Args are '{0}'".format_with(uninstallArgs.escape_curly_braces())); if (!key.HasQuietUninstall && installer.GetType() == typeof(CustomInstaller)) { var skipUninstaller = true; var timeout = config.PromptForConfirmation ? 0 : 30; var selection = InteractivePrompt.prompt_for_confirmation( "Uninstall may not be silent (could not detect). Proceed?", new[] { "yes", "no" }, defaultChoice: "no", requireAnswer: true, allowShortAnswer: true, shortPrompt: true, timeoutInSeconds: timeout ); if (selection.is_equal_to("yes")) { skipUninstaller = false; } if (skipUninstaller) { this.Log().Info(" Skipping auto uninstaller - Installer type was not detected and no silent uninstall key exists."); this.Log().Warn("If the application was not removed with a chocolateyUninstall.ps1,{0} please remove it from Programs and Features manually.".format_with(Environment.NewLine)); return; } } var exitCode = _commandExecutor.execute( uninstallExe, uninstallArgs.trim_safe(), config.CommandExecutionTimeoutSeconds, (s, e) => { if (e == null || string.IsNullOrWhiteSpace(e.Data)) { return; } this.Log().Info(() => " [AutoUninstaller] {0}".format_with(e.Data.escape_curly_braces())); }, (s, e) => { if (e == null || string.IsNullOrWhiteSpace(e.Data)) { return; } this.Log().Error(() => " [AutoUninstaller] {0}".format_with(e.Data.escape_curly_braces())); }, updateProcessPath: false); if (!installer.ValidUninstallExitCodes.Contains(exitCode)) { Environment.ExitCode = exitCode; string logMessage = " Auto uninstaller failed. Please remove machine installation manually.{0} Exit code was {1}".format_with(Environment.NewLine, exitCode); this.Log().Error(() => logMessage.escape_curly_braces()); packageResult.Messages.Add(new ResultMessage(config.Features.FailOnAutoUninstaller ? ResultType.Error : ResultType.Warn, logMessage)); } else { this.Log().Info(() => " Auto uninstaller has successfully uninstalled {0} or detected previous uninstall.".format_with(packageResult.Package.Id)); } }
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"); } } }