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); }
/// <summary> /// Search the system for valid uninstallers, parse them into coherent objects and return the resulting list. /// </summary> /// <exception cref="System.Security.SecurityException"> /// The user does not have the permissions required to read the /// registry key. /// </exception> /// <exception cref="ObjectDisposedException"> /// The <see cref="T:Microsoft.Win32.RegistryKey" /> is closed (closed keys /// cannot be accessed). /// </exception> /// <exception cref="UnauthorizedAccessException">The user does not have the necessary registry rights.</exception> /// <exception cref="IOException">A system error occurred, for example the current key has been deleted.</exception> public static IEnumerable <ApplicationUninstallerEntry> GetUninstallerList(GetUninstallerListCallback callback) { PopulateWindowsInstallerValidGuids(); var keysToCheck = GetRegistryKeys(); var uninstallersToCreate = new List <KeyValuePair <RegistryKey, bool> >(); foreach (var kvp in keysToCheck.Where(kvp => kvp.Key != null)) { uninstallersToCreate.AddRange(from subkeyName in kvp.Key.GetSubKeyNames() select kvp.Key.OpenSubKey(subkeyName) into subkey where subkey != null select new KeyValuePair <RegistryKey, bool>(subkey, kvp.Value)); kvp.Key.Close(); } var itemId = 0; var applicationUninstallers = new List <ApplicationUninstallerEntry>(); foreach (var uninstallerToCreate in uninstallersToCreate) { try { var entry = ApplicationUninstallerFactory.TryCreateFromRegistry(uninstallerToCreate.Key, uninstallerToCreate.Value); if (entry != null) { applicationUninstallers.Add(entry); } } catch { //Uninstaller is invalid or there is no uninstaller in the first place. Skip it to avoid problems. } finally { uninstallerToCreate.Key.Close(); itemId++; var progress = new GetUninstallerListProgress(uninstallersToCreate.Count) { CurrentCount = itemId }; callback(progress); } } applicationUninstallers.AddRange(ApplicationUninstallerFactory.GetStoreApps()); if (ApplicationUninstallerFactory.SteamHelperIsAvailable) { var steamAppsOnDisk = ApplicationUninstallerFactory.GetSteamApps().ToList(); foreach (var steamApp in applicationUninstallers.Where(x => x.UninstallerKind == UninstallerType.Steam)) { var toRemove = steamAppsOnDisk.FindAll(x => x.InstallLocation.Equals(steamApp.InstallLocation, StringComparison.InvariantCultureIgnoreCase)); steamAppsOnDisk.RemoveAll(toRemove); ApplicationUninstallerFactory.ChangeSteamAppUninstallStringToHelper(steamApp); if (steamApp.EstimatedSize.IsDefault() && toRemove.Any()) { steamApp.EstimatedSize = toRemove.First().EstimatedSize; } } foreach (var steamApp in steamAppsOnDisk) { ApplicationUninstallerFactory.ChangeSteamAppUninstallStringToHelper(steamApp); } applicationUninstallers.AddRange(steamAppsOnDisk); } applicationUninstallers.AddRange(ApplicationUninstallerFactory.GetSpecialUninstallers(applicationUninstallers)); // Fill in missing information foreach (var applicationUninstaller in applicationUninstallers) { if (applicationUninstaller.IconBitmap == null) { string iconPath; applicationUninstaller.IconBitmap = ApplicationUninstallerFactory.TryGetIcon( applicationUninstaller, out iconPath); applicationUninstaller.DisplayIcon = iconPath; } if (applicationUninstaller.InstallDate.IsDefault() && Directory.Exists(applicationUninstaller.InstallLocation)) { applicationUninstaller.InstallDate = Directory.GetCreationTime(applicationUninstaller.InstallLocation); } } return(applicationUninstallers); }