public static void extract_all_resources_to_relative_directory(IFileSystem fileSystem, IAssembly assembly, string directoryPath, IList<string> relativeDirectories, string resourcesToInclude, bool overwriteExisting = false, bool logOutput = false)
        {
            var resourceString = new StringBuilder();
            foreach (var resourceName in assembly.GetManifestResourceNames())
            {
                if (!resourceName.StartsWith(resourcesToInclude))
                {
                    continue;
                }
                resourceString.Clear();
                resourceString.Append(resourceName);

                //var fileExtensionLocation = resourceName.LastIndexOf('.');
                //resourceString.Remove(fileExtensionLocation, resourceString.Length - fileExtensionLocation);
                resourceString.Replace(resourcesToInclude + ".", "");
                foreach (var directory in relativeDirectories)
                {
                    resourceString.Replace("{0}".format_with(directory), "{0}{1}".format_with(directory, fileSystem.get_path_directory_separator_char()));
                }

                // replacing \. with \
                resourceString.Replace("{0}.".format_with(fileSystem.get_path_directory_separator_char()), "{0}".format_with(fileSystem.get_path_directory_separator_char()));

                var fileLocation = resourceString.ToString();
                //var fileLocation = fileSystem.combine_paths("", resourceString.ToString().Split('.')) + resourceName.Substring(fileExtensionLocation);

                var filePath = fileSystem.combine_paths(directoryPath, fileLocation);
                if (logOutput) "chocolatey".Log().Debug("Unpacking {0} to '{1}'".format_with(fileLocation,filePath));
                extract_binary_file_from_assembly(fileSystem, assembly, resourceName, filePath, overwriteExisting);
            }
        }
Example #2
0
        private static void set_config_items(ChocolateyConfiguration config, ConfigFileSettings configFileSettings, IFileSystem fileSystem)
        {
            var cacheLocation = set_config_item(ApplicationParameters.ConfigSettings.CacheLocation, configFileSettings, string.IsNullOrWhiteSpace(configFileSettings.CacheLocation) ? string.Empty : configFileSettings.CacheLocation, "Cache location if not TEMP folder.");
            config.CacheLocation = !string.IsNullOrWhiteSpace(cacheLocation) ? cacheLocation : fileSystem.combine_paths(fileSystem.get_temp_path(), "chocolatey"); // System.Environment.GetEnvironmentVariable("TEMP");
            if (string.IsNullOrWhiteSpace(config.CacheLocation))
            {
                config.CacheLocation = fileSystem.combine_paths(ApplicationParameters.InstallLocation, "temp");
            }

            var originalCommandTimeout = configFileSettings.CommandExecutionTimeoutSeconds;
            var commandExecutionTimeoutSeconds = -1;
            int.TryParse(
                set_config_item(
                    ApplicationParameters.ConfigSettings.CommandExecutionTimeoutSeconds,
                    configFileSettings,
                    originalCommandTimeout == 0 ?
                        ApplicationParameters.DefaultWaitForExitInSeconds.to_string()
                        : originalCommandTimeout.to_string(),
                    "Default timeout for command execution."),
                out commandExecutionTimeoutSeconds);
            config.CommandExecutionTimeoutSeconds = commandExecutionTimeoutSeconds;
            if (configFileSettings.CommandExecutionTimeoutSeconds <= 0)
            {
                set_config_item(ApplicationParameters.ConfigSettings.CommandExecutionTimeoutSeconds, configFileSettings, ApplicationParameters.DefaultWaitForExitInSeconds.to_string(), "Default timeout for command execution.", forceSettingValue: true);
                config.CommandExecutionTimeoutSeconds = ApplicationParameters.DefaultWaitForExitInSeconds;
            }

            config.ContainsLegacyPackageInstalls = set_config_item(ApplicationParameters.ConfigSettings.ContainsLegacyPackageInstalls, configFileSettings, "true", "Install has packages installed prior to 0.9.9 series.").is_equal_to(bool.TrueString);
            config.Proxy.Location = set_config_item(ApplicationParameters.ConfigSettings.Proxy, configFileSettings, string.Empty, "Explicit proxy location.");
            config.Proxy.User = set_config_item(ApplicationParameters.ConfigSettings.ProxyUser, configFileSettings, string.Empty, "Optional proxy user.");
            config.Proxy.EncryptedPassword = set_config_item(ApplicationParameters.ConfigSettings.ProxyPassword, configFileSettings, string.Empty, "Optional proxy password. Encrypted.");

            int minPositives=0;
            int.TryParse(set_config_item(ApplicationParameters.ConfigSettings.VirusCheckMinimumPositives, configFileSettings, "5", "Optional proxy password. Encrypted."), out minPositives);
            config.VirusCheckMinimumPositives = minPositives == 0 ? 5 : minPositives;
        }
        private static void set_file_configuration(ChocolateyConfiguration config, IFileSystem fileSystem, IXmlService xmlService, Action<string> notifyWarnLoggingAction)
        {
            var globalConfigPath = ApplicationParameters.GlobalConfigFileLocation;
            AssemblyFileExtractor.extract_text_file_from_assembly(fileSystem, Assembly.GetExecutingAssembly(), ApplicationParameters.ChocolateyConfigFileResource, globalConfigPath);

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

            set_machine_sources(config, configFileSettings);

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

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

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

            set_feature_flags(config, configFileSettings);

            // save so all updated configuration items get set to existing config
            FaultTolerance.try_catch_with_logging_exception(
                () => xmlService.serialize(configFileSettings, globalConfigPath),
                "Error updating '{0}'. Please ensure you have permissions to do so".format_with(globalConfigPath),
                logWarningInsteadOfError: true);
        }
Example #4
0
 private static void remove_old_chocolatey_exe(IFileSystem fileSystem)
 {
     try
     {
         fileSystem.delete_file(fileSystem.get_current_assembly_path() + ".old");
         fileSystem.delete_file(fileSystem.combine_paths(AppDomain.CurrentDomain.BaseDirectory, "choco.exe.old"));
     }
     catch (Exception ex)
     {
         "chocolatey".Log().Warn("Attempting to delete choco.exe.old ran into an issue:{0} {1}".format_with(Environment.NewLine, ex.Message));
     }
 }
Example #5
0
        public void noop(ChocolateyConfiguration configuration)
        {
            var templateLocation = _fileSystem.combine_paths(configuration.OutputDirectory ?? _fileSystem.get_current_directory(), configuration.NewCommand.Name);

            this.Log().Info(() => "Would have generated a new package specification at {0}".format_with(templateLocation));
        }
Example #6
0
        public void run(PackageResult packageResult, ChocolateyConfiguration config)
        {
            if (!config.Features.AutoUninstaller)
            {
                this.Log().Info(" Skipping auto uninstaller - AutoUninstaller feature is not enabled.");
                return;
            }

            var pkgInfo = _packageInfoService.get_package_information(packageResult.Package);

            if (pkgInfo.RegistrySnapshot == null)
            {
                this.Log().Info(" Skipping auto uninstaller - No registry snapshot.");
                return;
            }

            var registryKeys = pkgInfo.RegistrySnapshot.RegistryKeys;
            if (registryKeys == null || registryKeys.Count == 0)
            {
                this.Log().Info(" Skipping auto uninstaller - No registry keys in snapshot.");
                return;
            }

            this.Log().Info(" Running auto uninstaller...");
            if (WaitForCleanup)
            {
                this.Log().Debug("Sleeping for {0} seconds to allow Windows to finish cleaning up.".format_with(SLEEP_TIME));
                Thread.Sleep((int)TimeSpan.FromSeconds(SLEEP_TIME).TotalMilliseconds);
            }

            foreach (var key in registryKeys.or_empty_list_if_null())
            {
                this.Log().Debug(() => " Preparing uninstall key '{0}'".format_with(key.UninstallString.escape_curly_braces()));

                if ((!string.IsNullOrWhiteSpace(key.InstallLocation) && !_fileSystem.directory_exists(key.InstallLocation)) || !_registryService.installer_value_exists(key.KeyPath, ApplicationParameters.RegistryValueInstallLocation))
                {
                    this.Log().Info(" Skipping auto uninstaller - The application appears to have been uninstalled already by other means.");
                    this.Log().Debug(() => " Searched for install path '{0}' - found? {1}".format_with(key.InstallLocation.escape_curly_braces(), _fileSystem.directory_exists(key.InstallLocation)));
                    this.Log().Debug(() => " Searched for registry key '{0}' value '{1}' - found? {2}".format_with(key.KeyPath.escape_curly_braces(), ApplicationParameters.RegistryValueInstallLocation, _registryService.installer_value_exists(key.KeyPath, ApplicationParameters.RegistryValueInstallLocation)));
                    continue;
                }

                // split on " /" and " -" for quite a bit more accuracy
                IList<string> uninstallArgsSplit = key.UninstallString.to_string().Split(new[] {" /", " -"}, StringSplitOptions.RemoveEmptyEntries).ToList();
                var uninstallExe = uninstallArgsSplit.DefaultIfEmpty(string.Empty).FirstOrDefault();
                var uninstallArgs = key.UninstallString.to_string().Replace(uninstallExe.to_string(), string.Empty);
                uninstallExe = uninstallExe.remove_surrounding_quotes();
                this.Log().Debug(() => " Uninstaller path is '{0}'".format_with(uninstallExe));

                IInstaller installer = new CustomInstaller();

                switch (key.InstallerType)
                {
                    case InstallerType.Msi:
                        installer = new MsiInstaller();
                        break;
                    case InstallerType.InnoSetup:
                        installer = new InnoSetupInstaller();
                        break;
                    case InstallerType.Nsis:
                        installer = new NsisInstaller();
                        break;
                    case InstallerType.InstallShield:
                        installer = new InstallShieldInstaller();
                        break;
                }

                this.Log().Debug(() => " Installer type is '{0}'".format_with(installer.GetType().Name));

                if (key.InstallerType == InstallerType.Msi)
                {
                    // because sometimes the key is set with /i to allow for modify :/
                    uninstallArgs = uninstallArgs.Replace("/I{", "/X{");
                    uninstallArgs = uninstallArgs.Replace("/i{", "/X{");
                    uninstallArgs = uninstallArgs.Replace("/I ", "/X ");
                    uninstallArgs = uninstallArgs.Replace("/i ", "/X ");
                }

                if (!key.HasQuietUninstall)
                {
                    //todo: ultimately we should merge keys
                    uninstallArgs += " " + installer.build_uninstall_command_arguments();
                }

                var packageCacheLocation = _fileSystem.combine_paths(_fileSystem.get_full_path(config.CacheLocation), pkgInfo.Package.Id, pkgInfo.Package.Version.to_string());
                this.Log().Debug(() => " Setting up uninstall logging directory at {0}".format_with(packageCacheLocation.escape_curly_braces()));
                _fileSystem.create_directory_if_not_exists(_fileSystem.get_directory_name(packageCacheLocation));
                uninstallArgs = uninstallArgs.Replace(InstallTokens.PACKAGE_LOCATION, packageCacheLocation);
                uninstallArgs = uninstallArgs.Replace(InstallTokens.TEMP_LOCATION, packageCacheLocation);

                this.Log().Debug(() => " Args are '{0}'".format_with(uninstallArgs.escape_curly_braces()));

                if (!key.HasQuietUninstall &&  installer.GetType() == typeof(CustomInstaller))
                {
                    var skipUninstaller = true;

                    var timeout = config.PromptForConfirmation ? 0 : 30;

                    var selection = InteractivePrompt.prompt_for_confirmation(
                        "Uninstall may not be silent (could not detect). Proceed?",
                        new[] { "yes", "no" },
                        defaultChoice: "no",
                        requireAnswer: true,
                        allowShortAnswer: true,
                        shortPrompt: true,
                        timeoutInSeconds: timeout
                        );
                    if (selection.is_equal_to("yes")) skipUninstaller = false;

                    if (skipUninstaller)
                    {
                        this.Log().Info(" Skipping auto uninstaller - Installer type was not detected and no silent uninstall key exists.");
                        this.Log().Warn("If the application was not removed with a chocolateyUninstall.ps1,{0} please remove it from Programs and Features manually.".format_with(Environment.NewLine));
                        return;
                    }
                }

                var exitCode = _commandExecutor.execute(
                    uninstallExe,
                    uninstallArgs.trim_safe(),
                    config.CommandExecutionTimeoutSeconds,
                    (s, e) =>
                        {
                            if (e == null || string.IsNullOrWhiteSpace(e.Data)) return;
                            this.Log().Info(() => " [AutoUninstaller] {0}".format_with(e.Data.escape_curly_braces()));
                        },
                    (s, e) =>
                        {
                            if (e == null || string.IsNullOrWhiteSpace(e.Data)) return;
                            this.Log().Error(() => " [AutoUninstaller] {0}".format_with(e.Data.escape_curly_braces()));
                        },
                    updateProcessPath: false);

                if (!installer.ValidUninstallExitCodes.Contains(exitCode))
                {
                    Environment.ExitCode = exitCode;
                    string logMessage = " Auto uninstaller failed. Please remove machine installation manually.{0} Exit code was {1}".format_with(Environment.NewLine, exitCode);
                    this.Log().Error(() => logMessage.escape_curly_braces());
                    packageResult.Messages.Add(new ResultMessage(config.Features.FailOnAutoUninstaller ? ResultType.Error : ResultType.Warn, logMessage));
                }
                else
                {
                    this.Log().Info(() => " Auto uninstaller has successfully uninstalled {0} or detected previous uninstall.".format_with(packageResult.Package.Id));
                }
            }
        }
Example #7
0
        public void install(ChocolateyConfiguration configuration, PackageResult packageResult)
        {
            _fileSystem.create_directory_if_not_exists(ApplicationParameters.ShimsLocation);

            if (packageResult.InstallLocation.is_equal_to(ApplicationParameters.InstallLocation) || packageResult.InstallLocation.is_equal_to(ApplicationParameters.PackagesLocation))
            {
                var logMessage = "Install location is not specific enough, cannot run shimgen:{0} Erroneous install location captured as '{1}'".format_with(Environment.NewLine, packageResult.InstallLocation);
                packageResult.Messages.Add(new ResultMessage(ResultType.Warn, logMessage));
                this.Log().Error(logMessage.escape_curly_braces());
                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.escape_curly_braces()));
                },
                    (s, e) =>
                {
                    if (string.IsNullOrWhiteSpace(e.Data))
                    {
                        return;
                    }
                    this.Log().Error(() => " [ShimGen] {0}".format_with(e.Data.escape_curly_braces()));
                },
                    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));
                }
            }
        }
Example #8
0
 private string get_helpers_folder()
 {
     return(_fileSystem.combine_paths(ApplicationParameters.InstallLocation, "helpers"));
 }
Example #9
0
 private static void remove_old_chocolatey_exe(IFileSystem fileSystem)
 {
     fileSystem.delete_file(Assembly.GetExecutingAssembly().Location + ".old");
     fileSystem.delete_file(fileSystem.combine_paths(AppDomain.CurrentDomain.BaseDirectory, "choco.exe.old"));
 }
        //// 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) =>
                {
                    if (!string.IsNullOrWhiteSpace(e.Data))
                    {
                        this.Log().Warn("{0}".format_with(e.Data));
                    }
                },
                                                             false,
                                                             false);

                return(output);
            }
            catch (Exception ex)
            {
                this.Log().Warn("Unable to detect type for '{0}':{1} {2}".format_with(_fileSystem.get_file_name(filePath), Environment.NewLine, ex.Message));
                return(string.Empty);
            }
        }
Example #11
0
        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.");

                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 (!_fileSystem.file_exists(_configuration.VboxIdPath))
                    {
                        return;
                    }
                    var vmId = _fileSystem.read_file(_configuration.VboxIdPath);
                    if (string.IsNullOrWhiteSpace(vmId))
                    {
                        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;
                        }
                        var vmId = _fileSystem.read_file(_configuration.VboxIdPath);
                        if (string.IsNullOrWhiteSpace(vmId))
                        {
                            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);
            //}
        }