public static IEnumerable <ApplicationUninstallerEntry> GetApplicationsFromDrive(
            IEnumerable <ApplicationUninstallerEntry> existingUninstallerEntries, GetUninstallerListCallback callback)
        {
            var existingUninstallers = existingUninstallerEntries as IList <ApplicationUninstallerEntry> ??
                                       existingUninstallerEntries.ToList();

            var pfDirectories = UninstallToolsGlobalConfig.GetProgramFilesDirectories(true).ToList();

            // Get directories which are already used and should be skipped
            var directoriesToSkip = existingUninstallers.SelectMany(x =>
            {
                if (!string.IsNullOrEmpty(x.DisplayIcon))
                {
                    try
                    {
                        var iconFilename = x.DisplayIcon.Contains('.')
                            ? ProcessTools.SeparateArgsFromCommand(x.DisplayIcon).FileName
                            : x.DisplayIcon;

                        return(new[] { x.InstallLocation, x.UninstallerLocation, PathTools.GetDirectory(iconFilename) });
                    }
                    catch
                    {
                        // Ignore invalid DisplayIcon paths
                    }
                }
                return(new[] { x.InstallLocation, x.UninstallerLocation });
            }).Where(x => x.IsNotEmpty()).Select(PathTools.PathToNormalCase)
                                    .Where(x => !pfDirectories.Any(pfd => pfd.Key.FullName.Contains(x, StringComparison.InvariantCultureIgnoreCase)))
                                    .Distinct().ToList();

            // Get sub directories which could contain user programs
            var directoriesToCheck = pfDirectories.Aggregate(Enumerable.Empty <KeyValuePair <DirectoryInfo, bool?> >(),
                                                             (a, b) => a.Concat(b.Key.GetDirectories().Select(x => new KeyValuePair <DirectoryInfo, bool?>(x, b.Value))));

            // Get directories that can be relatively safely checked
            var inputs = directoriesToCheck.Where(x => !directoriesToSkip.Any(y =>
                                                                              x.Key.FullName.Contains(y, StringComparison.InvariantCultureIgnoreCase) ||
                                                                              y.Contains(x.Key.FullName, StringComparison.InvariantCultureIgnoreCase))).ToList();

            var results = new List <ApplicationUninstallerEntry>();
            var itemId  = 0;

            foreach (var directory in inputs)
            {
                itemId++;

                var progress = new GetUninstallerListProgress(inputs.Count)
                {
                    CurrentCount = itemId
                };
                callback(progress);

                if (UninstallToolsGlobalConfig.IsSystemDirectory(directory.Key) ||
                    directory.Key.Name.StartsWith("Windows", StringComparison.InvariantCultureIgnoreCase))
                {
                    continue;
                }

                //Try to get the main executable from the filtered folders. If no executables are present check subfolders.
                var detectedEntries = ApplicationUninstallerFactory.TryCreateFromDirectory(directory.Key,
                                                                                           directory.Value);

                results.AddRange(detectedEntries.Where(detected => !existingUninstallers.Any(existing =>
                {
                    if (!string.IsNullOrEmpty(existing.DisplayName) && !string.IsNullOrEmpty(detected.DisplayNameTrimmed) &&
                        existing.DisplayName.Contains(detected.DisplayNameTrimmed))
                    {
                        return(!existing.IsInstallLocationValid() ||
                               detected.InstallLocation.Contains(existing.InstallLocation,
                                                                 StringComparison.CurrentCultureIgnoreCase));
                    }
                    return(false);
                })));

                //if (result != null && !existingUninstallers.Any(x => x.DisplayName.Contains(result.DisplayNameTrimmed)))
                //    results.Add(result);
            }

            return(results);
        }
        public void UninstallFromDirectory(IEnumerable <ApplicationUninstallerEntry> allUninstallers)
        {
            if (!TryGetUninstallLock())
            {
                return;
            }
            var listRefreshNeeded = false;

            var applicationUninstallerEntries = allUninstallers as IList <ApplicationUninstallerEntry> ?? allUninstallers.ToList();

            try
            {
                var dialog = new FolderBrowserDialog
                {
                    RootFolder  = Environment.SpecialFolder.Desktop,
                    Description = Localisable.UninstallFromDirectory_FolderBrowse
                };

                if (dialog.ShowDialog(MessageBoxes.DefaultOwner) != DialogResult.OK)
                {
                    return;
                }

                var items = new List <ApplicationUninstallerEntry>();
                LoadingDialog.ShowDialog(Localisable.UninstallFromDirectory_ScanningTitle,
                                         _ =>
                {
                    items.AddRange(ApplicationUninstallerFactory.TryCreateFromDirectory(
                                       new DirectoryInfo(dialog.SelectedPath), null));
                });

                if (items.Count == 0)
                {
                    items.AddRange(applicationUninstallerEntries
                                   .Where(x => PathTools.PathsEqual(dialog.SelectedPath, x.InstallLocation)));
                }

                if (items.Count == 0)
                {
                    MessageBoxes.UninstallFromDirectoryNothingFound();
                }
                else
                {
                    foreach (var item in items.ToList())
                    {
                        if (item.UninstallPossible && item.UninstallerKind != UninstallerType.SimpleDelete &&
                            MessageBoxes.UninstallFromDirectoryUninstallerFound(item.DisplayName, item.UninstallString))
                        {
                            item.RunUninstaller(false, Settings.Default.AdvancedSimulate).WaitForExit(60000);
                            items.Remove(item);
                            listRefreshNeeded = true;
                        }
                        else
                        {
                            var found = applicationUninstallerEntries.Where(
                                x => PathTools.PathsEqual(item.InstallLocation, x.InstallLocation)).ToList();

                            if (!found.Any())
                            {
                                continue;
                            }

                            items.Remove(item);

                            foreach (var entry in found)
                            {
                                if (entry.UninstallPossible && entry.UninstallerKind != UninstallerType.SimpleDelete &&
                                    MessageBoxes.UninstallFromDirectoryUninstallerFound(entry.DisplayName, entry.UninstallString))
                                {
                                    try { item.RunUninstaller(false, Settings.Default.AdvancedSimulate).WaitForExit(60000); }
                                    catch (Exception ex) { PremadeDialogs.GenericError(ex); }

                                    listRefreshNeeded = true;
                                }
                                else
                                {
                                    items.Add(entry);
                                }
                            }
                        }
                    }

                    AdvancedUninstall(items, applicationUninstallerEntries.Where(
                                          x => !items.Any(y => PathTools.PathsEqual(y.InstallLocation, x.InstallLocation))));
                }
            }
            finally
            {
                ReleaseUninstallLock();
                _lockApplication(false);
                if (listRefreshNeeded)
                {
                    _initiateListRefresh();
                }
            }
        }