/// <summary>
        /// Searches the registry to get a list of installed apps on the computer.
        /// </summary>
        /// <returns>Returns a list of "Application".</returns>
        public static List<Application> GetInstalledApplications()
        {
            //Retrieve installed application details:
            //Name, VendorName, Version, InstallDate
            var regReader = new RegistryReader();
            var installedApps = new List<Application>();

            Logger.Log("Retrieving installed applications.");

            try
            {
                var myreg = regReader.GetAllInstalledApplicationDetails();

                foreach (var x in myreg.Where(p => p.Name != ""))
                {
                    var app = new Application();
                    app.VendorName = (String.IsNullOrEmpty(x.VendorName) ? String.Empty : x.VendorName);
                    app.Name = (String.IsNullOrEmpty(x.Name) ? String.Empty : x.Name);
                    app.Version = (String.IsNullOrEmpty(x.Version) ? String.Empty : x.Version);

                    try
                    {
                        app.InstallDate = Convert.ToDouble(x.Date);
                    }
                    catch (Exception)
                    {
                        app.InstallDate = 0.0;
                    }

                    app.Status = "Installed";

                    Logger.Log(app.Name, LogLevel.Info);

                    installedApps.Add(app);
                }
            }
            catch (Exception e)
            {
                Logger.Log("Failed to get installed application details. Skipping.", LogLevel.Error);
                Logger.LogException(e);
            }

            return installedApps;
        }
        private void UninstallOperation(RvSofOperation operation)
        {
            var registry = new RegistryReader();
            var tempAppsToAdd = new List<RVsofResult.AppsToAdd2>();
            var tempAppsToDelete = new List<RVsofResult.AppsToDelete2>();
            var savedOperations = Operations.LoadOpDirectory().Where(p => p.operation == OperationValue.Uninstall).ToList();

            if (!savedOperations.Any())
            {
                Logger.Log("There are no operations remaining, Unable to uninstall app: {0}", LogLevel.Warning, operation.Type);
                return;
            }

            foreach (var localOp in savedOperations)
            {
                if (operation.ListOfInstalledApps.Any()) operation.ListOfInstalledApps.Clear();
                if (operation.ListOfAppsAfterInstall.Any()) operation.ListOfAppsAfterInstall.Clear();

                //Retrieve a list of all updates installed in the system before uninstalling anything.
                operation.ListOfInstalledApps = registry.GetRegistryInstalledApplicationNames();
                Operations.UpdateStatus(localOp, Operations.OperationStatus.Processing);

                var msiUninstall = new MSIUninstaller.MSIprop();
                try
                {
                    if (localOp.filedata_app_name != String.Empty)
                        msiUninstall = MSIUninstaller.UnistallApp(localOp.filedata_app_name);
                }
                catch
                {
                    Logger.Log("MSIuninstaller crashed while attempting to uninstall {0}", LogLevel.Error, localOp.filedata_app_name);
                    msiUninstall.UninstallPass = false;
                }

                Application update = null;
                if (!msiUninstall.UninstallPass)
                {
                    var installedUpdates = WindowsUpdates.GetInstalledUpdates();
                    update = (from n in installedUpdates where n.Name == localOp.filedata_app_name select n).FirstOrDefault();
                }

                var uninstallerResults = new UninstallerResults();
                if (!msiUninstall.UninstallPass)
                {
                    try
                    {
                        uninstallerResults = WindowsUninstaller.Uninstall(update);
                    }
                    catch
                    {
                        Logger.Log("Windows Uninstall Update failed.", LogLevel.Error);
                        uninstallerResults.Success = false;
                    }
                }

                //Get all installed application after installing..
                operation.ListOfAppsAfterInstall = registry.GetRegistryInstalledApplicationNames();

                //GET DATA FOR APPSTOADD/APPSTODELETE
                var appListToDelete = RegistryReader.GetAppsToDelete(operation.ListOfInstalledApps, operation.ListOfAppsAfterInstall);
                var appListToAdd    = RegistryReader.GetAppsToAdd(operation.ListOfInstalledApps, operation.ListOfAppsAfterInstall);

                //APPS TO DELETE
                #region Apps to Delete
                if (appListToDelete != null)
                {
                    var temp = registry.GetAllInstalledApplicationDetails();
                    foreach (var app in appListToDelete)
                    {
                        var appsToDelete = new RVsofResult.AppsToDelete2();
                        var version = (from d in temp where d.Name == localOp.filedata_app_name select d.Version).FirstOrDefault();

                        appsToDelete.Name = (String.IsNullOrEmpty(app)) ? String.Empty : app;
                        appsToDelete.Version = (String.IsNullOrEmpty(version)) ? String.Empty : version;

                        tempAppsToDelete.Add(appsToDelete);
                    }
                }
                #endregion

                //APPS TO ADD
                #region Apps to Add
                if (appListToAdd != null)
                {
                    var installedAppsDetails = registry.GetAllInstalledApplicationDetails();

                    foreach (var app in appListToAdd)
                    {
                        var temp = new RVsofResult.AppsToAdd2();
                        var localApp = app;
                        var version = (from d in installedAppsDetails where d.Name == localOp.filedata_app_name select d.Version).FirstOrDefault(); //Default NULL
                        var vendor = (from d in installedAppsDetails where d.Name == localApp select d.VendorName).FirstOrDefault(); //Default NULL
                        var installDate = Tools.ConvertDateToEpoch((from d in installedAppsDetails where d.Name == localApp select d.Date).FirstOrDefault()); //Default 0.0D

                        temp.AppsToAdd.Name = (String.IsNullOrEmpty(localApp)) ? String.Empty : localApp;
                        temp.AppsToAdd.Version = (String.IsNullOrEmpty(version)) ? String.Empty : version;
                        temp.AppsToAdd.InstallDate = (installDate.Equals(0.0D)) ? 0.0D : installDate;
                        temp.AppsToAdd.VendorName = (String.IsNullOrEmpty(vendor)) ? String.Empty : vendor;
                        temp.AppsToAdd.RebootRequired = "no";
                        temp.AppsToAdd.ReleaseDate = 0.0;
                        temp.AppsToAdd.Status = "installed";
                        temp.AppsToAdd.Description = String.Empty;
                        temp.AppsToAdd.SupportUrl = String.Empty;
                        temp.AppsToAdd.VendorId = String.Empty;
                        temp.AppsToAdd.VendorSeverity = String.Empty;
                        temp.AppsToAdd.KB = String.Empty;

                        tempAppsToAdd.Add(temp);
                    }
                }
                #endregion

                if (uninstallerResults.Success || msiUninstall.UninstallPass)
                {
                    // Success! Uinstalled OK
                    localOp.success = true.ToString().ToLower();
                    localOp.reboot_required = String.IsNullOrEmpty(uninstallerResults.Restart.ToString()) ? "no" : uninstallerResults.Restart.ToString();
                    localOp.error = string.Empty;

                    operation.Api = ApiCalls.RvUninstallOperation();
                    operation.Type = OperationValue.Uninstall;
                    operation.Id = localOp.operation_id;

                    InstallSendResults(localOp, operation, tempAppsToAdd, tempAppsToDelete);
                }
                else
                {
                    // Fail! Uinstalled Failed.
                    localOp.success = false.ToString().ToLower();
                    localOp.reboot_required = String.IsNullOrEmpty(uninstallerResults.Restart.ToString()) ? "no" : uninstallerResults.Restart.ToString();
                    localOp.error = "Unable to successfully uninstall application. If this is not a Windows Update Uninstall, ensure that the application is of type MSI We currently do not support other installers. Error: " + msiUninstall.Error;

                    operation.Api = ApiCalls.RvUninstallOperation();
                    operation.Type = OperationValue.Uninstall;
                    operation.Id = localOp.operation_id;

                    InstallSendResults(localOp, operation, tempAppsToAdd, tempAppsToDelete);
                }
            }
        }
        private void InstallSupportedApplication(RvSofOperation operation)
        {
            var registry         = new RegistryReader();
            var tempAppsToAdd    = new List<RVsofResult.AppsToAdd2>();
            var tempAppsToDelete = new List<RVsofResult.AppsToDelete2>();

            var savedOperations = Operations.LoadOpDirectory().Where(p=>p.operation == OperationValue.InstallSupportedApp).ToList();

            if (!savedOperations.Any())
            {
                Logger.Log("There are no operations remaining, Unable to install supported app: {0}", LogLevel.Warning, operation.Type);
                return;
            }

            foreach (var update in savedOperations)
            {
                if (operation.ListOfInstalledApps.Count > 0) operation.ListOfInstalledApps.Clear();
                if (operation.ListOfAppsAfterInstall.Count > 0) operation.ListOfAppsAfterInstall.Clear();

                operation.ListOfInstalledApps = registry.GetRegistryInstalledApplicationNames();

                Logger.Log("Preparing to Install {0}", LogLevel.Info, update.filedata_app_name);

                Operations.SavedOpData updateDownloadResults = Downloader.DownloadFile(update, Downloader.UpdateDirectories.SupportedAppDir);
                Operations.UpdateStatus(updateDownloadResults, Operations.OperationStatus.Processing);

                //If download fails, send back results to server and move to next package (if any)
                if (!String.IsNullOrEmpty(updateDownloadResults.error))
                {
                    InstallSendResults(updateDownloadResults, operation);
                    continue;
                }
                Logger.Log("Download completed for {0}", LogLevel.Info, update.filedata_app_name);

                Operations.SavedOpData updateInstallResults = SupportedAppsManager.InstallSupportedAppsOperation(updateDownloadResults);

                //Get all installed application after installing..
                operation.ListOfAppsAfterInstall = registry.GetRegistryInstalledApplicationNames();

                //GET DATA FOR APPSTOADD/APPSTODELETE
                var appListToDelete = RegistryReader.GetAppsToDelete(operation.ListOfInstalledApps, operation.ListOfAppsAfterInstall);
                var appListToAdd    = RegistryReader.GetAppsToAdd(operation.ListOfInstalledApps, operation.ListOfAppsAfterInstall);

                //APPS TO DELETE
                #region Apps to Delete
                if (appListToDelete != null)
                {
                    var temp = registry.GetAllInstalledApplicationDetails();
                    foreach (var app in appListToDelete)
                    {
                        var appsToDelete = new RVsofResult.AppsToDelete2();
                        var version = (from d in temp where d.Name == updateInstallResults.filedata_app_name select d.Version).FirstOrDefault();

                        appsToDelete.Name = (String.IsNullOrEmpty(app)) ? String.Empty : app;
                        appsToDelete.Version = (String.IsNullOrEmpty(version)) ? String.Empty : version;

                        tempAppsToDelete.Add(appsToDelete);
                    }
                }
                #endregion

                //APPS TO ADD
                #region Apps to Add
                if (appListToAdd != null)
                {
                    var installedAppsDetails = registry.GetAllInstalledApplicationDetails();

                    foreach (var app in appListToAdd)
                    {
                        var temp = new RVsofResult.AppsToAdd2();
                        var localApp = app;
                        var version = (from d in installedAppsDetails where d.Name == updateInstallResults.filedata_app_name select d.Version).FirstOrDefault(); //Default NULL
                        var vendor = (from d in installedAppsDetails where d.Name == localApp select d.VendorName).FirstOrDefault(); //Default NULL
                        var installDate = Tools.ConvertDateToEpoch((from d in installedAppsDetails where d.Name == localApp select d.Date).FirstOrDefault()); //Default 0.0D

                        temp.AppsToAdd.Name = (String.IsNullOrEmpty(localApp)) ? String.Empty : localApp;
                        temp.AppsToAdd.Version = (String.IsNullOrEmpty(version)) ? String.Empty : version;
                        temp.AppsToAdd.InstallDate = (installDate.Equals(0.0D)) ? 0.0D : installDate;
                        temp.AppsToAdd.VendorName = (String.IsNullOrEmpty(vendor)) ? String.Empty : vendor;
                        temp.AppsToAdd.RebootRequired = "no";
                        temp.AppsToAdd.ReleaseDate = 0.0;
                        temp.AppsToAdd.Status = "installed";
                        temp.AppsToAdd.Description = String.Empty;
                        temp.AppsToAdd.SupportUrl = String.Empty;
                        temp.AppsToAdd.VendorId = String.Empty;
                        temp.AppsToAdd.VendorSeverity = String.Empty;
                        temp.AppsToAdd.KB = String.Empty;

                        tempAppsToAdd.Add(temp);
                    }
                }
                #endregion

                InstallSendResults(updateInstallResults, operation, tempAppsToAdd, tempAppsToDelete);
            }
        }
        public static RvSofOperation InstallSupportedAppsOperation(RvSofOperation operation)
        {
            var foundApplications = new List<InstallSupportedData>();
            var registryOpen = new RegistryReader();

            //Load all
            foreach (var installData in operation.InstallSupportedDataList)
            {
                var appDir = Path.Combine(Settings.UpdateDirectory, installData.Id);
                var found = false;

                foreach (var item in installData.Uris)
                {
                    var split = item.Split(new[] { '/' });
                    var filename = split[split.Length - 1];
                    var filepath = Path.Combine(appDir, filename);

                    if (File.Exists(filepath))
                        found = true;
                    else
                    {
                        found = false;
                        break;
                    }
                }

                if (!found)
                {
                    var result = new RVsofResult();
                    result.AppId = installData.Id;
                    result.Error = "Update did not Download: " + Environment.NewLine
                                                + installData.Name + Environment.NewLine;
                    operation.AddResult(result);
                }
                else
                {
                    Logger.Log("Update Files: Downloaded OK");
                    foundApplications.Add(installData);
                }
            }

            foreach (InstallSupportedData id in foundApplications)
            {
                try
                {
                    var appDirectory = Path.Combine(Settings.UpdateDirectory, id.Id);
                    var appFiles = Directory.GetFiles(appDirectory);

                    foreach (string file in appFiles)
                    {
                        var extension = Path.GetExtension(file);
                        Result result;

                        switch (extension)
                        {
                            case Extension.Exe:

                                Logger.Log("Installing: {0}", LogLevel.Info, id.Name);
                                result = ExeInstall(file, id.CliOptions);

                                break;

                            case Extension.Msi:

                                Logger.Log("Installing: {0}", LogLevel.Info, id.Name);
                                result = MsiInstall(file, id.CliOptions);

                                break;

                            case Extension.Msp:

                                Logger.Log("Installing: {0}", LogLevel.Info, id.Name);
                                result = MspInstall(file, id.CliOptions);

                                break;

                            default:

                                throw new Exception(String.Format("{0} is not a supported file format.", extension));
                        }

                        if (!result.Success)
                        {
                            var results = new RVsofResult();
                            results.Success = false.ToString();
                            results.AppId = id.Id;
                            results.Error = String.Format("Failed to install {0}. {1}. Exit code: {2}.", file, result.ExitCodeMessage, result.ExitCode);
                            Logger.Log("Failed to install: {0}", LogLevel.Info, file);
                            operation.AddResult(results);
                            break;
                        }

                        // If the last file was reached without issues, all should be good.
                        if (appFiles[appFiles.Length - 1].Equals(file))
                        {
                            var results = new RVsofResult();

                            //Get new list of installed applications after finishing installing applications.
                            operation.ListOfAppsAfterInstall = registryOpen.GetRegistryInstalledApplicationNames();

                            results.Success = true.ToString();
                            results.AppId = id.Id;
                            results.RebootRequired = result.Restart.ToString();
                            results.Data.Name = registryOpen.GetSetFromTwoLists(operation.ListOfInstalledApps, operation.ListOfAppsAfterInstall); //TODO: Keep eye on this, possibly not needed anymore.
                            Logger.Log("Update Success: {0}", LogLevel.Debug, file);
                            operation.AddResult(results);
                        }
                    }
                }
                catch (Exception e)
                {
                    Logger.Log("Could not install {0}.", LogLevel.Error, id.Name);
                    Logger.LogException(e);

                    var result = new RVsofResult();
                    result.AppId = id.Id;
                    result.Error = String.Format("Failed to install. {0}.", e.Message);
                    operation.AddResult(result);
                }
            }

            return operation;
        }