public SelectAppDialog() { InitializeComponent(); // Sort items in list by name var view = CollectionViewSource.GetDefaultView(ProgramListItems); view.SortDescriptions.Add(new SortDescription(nameof(ProgramItem.Name), ListSortDirection.Ascending)); ProgramList.ItemsSource = view; UpdateThread = new Thread(() => { var searchPaths = new Queue <string>(); // Add Steam install locations try { string steamInstallPath = Registry.LocalMachine.OpenSubKey(@"Software\Wow6432Node\Valve\Steam")?.GetValue("InstallPath") as string; if (!string.IsNullOrEmpty(steamInstallPath) && Directory.Exists(steamInstallPath)) { searchPaths.Enqueue(Path.Combine(steamInstallPath, "steamapps", "common")); string steamConfig = File.ReadAllText(Path.Combine(steamInstallPath, "config", "config.vdf")); foreach (Match match in new Regex("\"BaseInstallFolder_[1-9]\"\\s+\"(.+)\"").Matches(steamConfig)) { searchPaths.Enqueue(Path.Combine(match.Groups[1].Value.Replace("\\\\", "\\"), "steamapps", "common")); } } } catch { } // Add Origin install locations try { string originConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Origin", "local.xml"); if (File.Exists(originConfigPath)) { var originConfig = new XmlDocument(); originConfig.Load(originConfigPath); foreach (string searchPath in originConfig["Settings"].ChildNodes.Cast <XmlNode>() .Where(x => x.Attributes["key"].Value == "DownloadInPlaceDir") .Select(x => x.Attributes["value"].Value)) { // Avoid adding short paths to the search paths so not to scan the entire drive if (searchPath.Length > 25) { searchPaths.Enqueue(searchPath); } } } } catch { } while (searchPaths.Count != 0) { if (SuspendUpdateThread) { SuspendUpdateThreadEvent.WaitOne(); } string searchPath = searchPaths.Dequeue(); try { var files = Directory.GetFiles(searchPath, "*.exe", SearchOption.TopDirectoryOnly).Where(x => // Exclude installer executables x.IndexOf("redis", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("unins", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("setup", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("patch", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("update", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("install", StringComparison.OrdinalIgnoreCase) < 0 && // Exclude common support executables x.IndexOf("report", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("support", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("register", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("activation", StringComparison.OrdinalIgnoreCase) < 0 && // Exclude common utility and launcher executables x.IndexOf("tool", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("crash", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("config", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("launch", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("plugin", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("benchmark", StringComparison.OrdinalIgnoreCase) < 0 && // Exclude various known executables like SteamVR and CEF x.IndexOf("steamvr", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("cefprocess", StringComparison.OrdinalIgnoreCase) < 0 && !x.Contains("svc")).ToArray(); // Services if (files.Length != 0) { const int SPLIT_SIZE = 10; for (int i = 0; i < files.Length; i += SPLIT_SIZE) { Dispatcher.Invoke(new Action <ArraySegment <string> >(arg => { foreach (var file in arg) { if (ProgramListItems.FirstOrDefault(x => x.Path == file) == null) { ProgramListItems.Add(new ProgramItem(file)); } } }), DispatcherPriority.Background, new ArraySegment <string>(files, i, Math.Min(SPLIT_SIZE, files.Length - i))); } // Give back control to the OS Thread.Sleep(10); } // Continue searching in sub-directories var directories = Directory.GetDirectories(searchPath).Where(x => // Avoid deep folder structures x.Count(c => c == '\\') < 10 && // Ignore certain folders that are unlikely to contain useful executables x.IndexOf("docs", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("cache", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("support", StringComparison.OrdinalIgnoreCase) < 0 && !x.Contains("Data") && // AppData, ProgramData, _Data !x.Contains("_CommonRedist") && !x.Contains("__Installer") && !x.Contains("\\$") && !x.Contains("\\.") && !x.Contains("\\Windows") && // Ignore various folders which are known to not contain useful executables x.IndexOf("steamvr", StringComparison.OrdinalIgnoreCase) < 0); foreach (var path in directories) { searchPaths.Enqueue(path); } } catch { // Ignore permission errors continue; } } // Hide progress bar after search has finished Dispatcher.BeginInvoke(new Action(() => ProgramListProgress.Visibility = Visibility.Collapsed)); }); UpdateThread.Start(); }
public SelectAppDialog() { InitializeComponent(); // Sort items in list by name var view = CollectionViewSource.GetDefaultView(ProgramListItems); view.SortDescriptions.Add(new SortDescription(nameof(ProgramItem.Name), ListSortDirection.Ascending)); ProgramList.ItemsSource = view; UpdateThread = new Thread(() => { var searchPaths = new Queue <string>(); // Add Steam install locations try { string steamInstallPath = Registry.LocalMachine.OpenSubKey(@"Software\Wow6432Node\Valve\Steam")?.GetValue("InstallPath") as string; if (!string.IsNullOrEmpty(steamInstallPath) && Directory.Exists(steamInstallPath)) { searchPaths.Enqueue(Path.Combine(steamInstallPath, "steamapps", "common")); string steamConfig = File.ReadAllText(Path.Combine(steamInstallPath, "config", "config.vdf")); foreach (Match match in new Regex("\"BaseInstallFolder_[1-9]\"\\s+\"(.+)\"").Matches(steamConfig)) { searchPaths.Enqueue(Path.Combine(match.Groups[1].Value.Replace("\\\\", "\\"), "steamapps", "common")); } } } catch { } // Add Origin install locations try { string originConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Origin", "local.xml"); if (File.Exists(originConfigPath)) { string originConfig = File.ReadAllText(originConfigPath); foreach (Match match in new Regex("value=\"(.+?)\".*key=\"DownloadInPlaceDir\"").Matches(originConfig)) { searchPaths.Enqueue(match.Groups[1].Value); } } } catch { } while (searchPaths.Count != 0) { string searchPath = searchPaths.Dequeue(); try { var files = Directory.GetFiles(searchPath, "*.exe", SearchOption.TopDirectoryOnly).Where(x => // Ignore common utility executables x.IndexOf("tool", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("redis", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("crash", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("setup", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("update", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("config", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("launch", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("plugin", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("steamvr", StringComparison.OrdinalIgnoreCase) < 0 && // Exclude SteamVR executables x.IndexOf("install", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("support", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("register", StringComparison.OrdinalIgnoreCase) < 0 && x.IndexOf("activation", StringComparison.OrdinalIgnoreCase) < 0).ToList(); if (files.Count != 0) { Dispatcher.BeginInvoke(new Action <List <string> >(arg => { foreach (var file in arg) { if (ProgramListItems.FirstOrDefault(x => x.Path == file) == null) { ProgramListItems.Add(new ProgramItem(file)); } } }), DispatcherPriority.Background, files); } // Continue searching in sub-directories var directories = Directory.GetDirectories(searchPath).Where(x => // Ignore certain folders that are unlikely to contain useful executables x.IndexOf("cache", StringComparison.OrdinalIgnoreCase) < 0 && !x.Contains("Data") && // AppData, ProgramData, _Data !x.Contains("_CommonRedist") && !x.Contains("\\$") && !x.Contains("\\.") && !x.Contains("\\Windows")).ToList(); foreach (var path in directories) { searchPaths.Enqueue(path); } } catch { // Ignore permission errors continue; } } // Hide progress bar after search has finished Dispatcher.BeginInvoke(new Action(() => ProgramListProgress.Visibility = Visibility.Collapsed)); }); UpdateThread.Start(); }
public SelectAppDialog() { InitializeComponent(); ProgramList.ItemsSource = CollectionViewSource.GetDefaultView(ProgramListItems); UpdateThread = new Thread(() => { var files = new List <string>(); #if !RESHADE_SETUP_USE_MUI_CACHE var searchPaths = new Queue <string>(); // Add Steam install locations try { string steamInstallPath = Registry.LocalMachine.OpenSubKey(@"Software\Wow6432Node\Valve\Steam")?.GetValue("InstallPath") as string; if (!string.IsNullOrEmpty(steamInstallPath) && Directory.Exists(steamInstallPath)) { searchPaths.Enqueue(Path.Combine(steamInstallPath, "steamapps", "common")); string steamConfig = File.ReadAllText(Path.Combine(steamInstallPath, "config", "config.vdf")); foreach (Match match in new Regex("\"BaseInstallFolder_[1-9]\"\\s+\"(.+)\"").Matches(steamConfig)) { searchPaths.Enqueue(Path.Combine(match.Groups[1].Value.Replace("\\\\", "\\"), "steamapps", "common")); } } } catch { } // Add Origin install locations try { string originConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Origin", "local.xml"); if (File.Exists(originConfigPath)) { var originConfig = new XmlDocument(); originConfig.Load(originConfigPath); foreach (string searchPath in originConfig["Settings"].ChildNodes.Cast <XmlNode>() .Where(x => x.Attributes["key"].Value == "DownloadInPlaceDir") .Select(x => x.Attributes["value"].Value)) { // Avoid adding short paths to the search paths so not to scan the entire drive if (searchPath.Length > 25) { searchPaths.Enqueue(searchPath); } } } } catch { } // Add Epic Games Launcher install location { string epicGamesInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Epic Games"); if (Directory.Exists(epicGamesInstallPath)) { searchPaths.Enqueue(epicGamesInstallPath); } } #else foreach (var name in new string[] { "Software\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\Shell\\MuiCache", "Software\\Microsoft\\Windows\\ShellNoRoam\\MUICache", "Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Compatibility Assistant\\Persisted", "Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Compatibility Assistant\\Store" }) { try { string[] values = Registry.CurrentUser.OpenSubKey(name)?.GetValueNames(); if (values != null) { files.AddRange(values); } } catch { // Ignore permission errors continue; } } #endif const int SPLIT_SIZE = 50; var items = new KeyValuePair <string, FileVersionInfo> [SPLIT_SIZE]; #if !RESHADE_SETUP_USE_MUI_CACHE while (searchPaths.Count != 0) { string searchPath = searchPaths.Dequeue(); try { files = Directory.GetFiles(searchPath, "*.exe", SearchOption.TopDirectoryOnly).ToList(); } catch { // Skip permission errors continue; } #endif for (int offset = 0; offset < files.Count; offset += SPLIT_SIZE) { if (SuspendUpdateThread) { SuspendUpdateThreadEvent.WaitOne(); } for (int i = 0; i < Math.Min(SPLIT_SIZE, files.Count - offset); ++i) { string path = files[offset + i]; if (Path.GetExtension(path) != ".exe" || !File.Exists(path)) { continue; } // Exclude common installer, support and launcher executables if (path.ContainsIgnoreCase("redis") || path.ContainsIgnoreCase("unins") || path.ContainsIgnoreCase("setup") || path.ContainsIgnoreCase("patch") || path.ContainsIgnoreCase("update") || path.ContainsIgnoreCase("install") || path.ContainsIgnoreCase("report") || path.ContainsIgnoreCase("support") || path.ContainsIgnoreCase("register") || path.ContainsIgnoreCase("activation") || path.ContainsIgnoreCase("diagnostics") || path.ContainsIgnoreCase("tool") || path.ContainsIgnoreCase("crash") || path.ContainsIgnoreCase("config") || path.ContainsIgnoreCase("launch") || path.ContainsIgnoreCase("plugin") || path.ContainsIgnoreCase("benchmark") || path.ContainsIgnoreCase("steamvr") || path.ContainsIgnoreCase("cefprocess") || path.Contains("svc") || // Ignore certain folders that are unlikely to contain useful executables path.ContainsIgnoreCase("docs") || path.ContainsIgnoreCase("cache") || path.ContainsIgnoreCase("support") || path.Contains("Data") || // AppData, ProgramData, _Data path.Contains("_CommonRedist") || path.Contains("__Installer") || path.Contains("\\$") || path.Contains("\\.") || path.Contains("\\Windows") || path.ContainsIgnoreCase("steamvr")) { continue; } items[i] = new KeyValuePair <string, FileVersionInfo>(path, FileVersionInfo.GetVersionInfo(path)); } Dispatcher.Invoke(new Action <KeyValuePair <string, FileVersionInfo>[]>(arg => { foreach (var item in arg) { if (item.Key == null || ProgramListItems.Any(x => x.Path == item.Key)) { continue; } ProgramListItems.Add(new ProgramItem(item.Key, item.Value)); } }), DispatcherPriority.Background, (object)items); // Give back control to the OS Thread.Sleep(5); } #if !RESHADE_SETUP_USE_MUI_CACHE // Continue searching in sub-directories foreach (var path in Directory.GetDirectories(searchPath)) { searchPaths.Enqueue(path); } } #endif // Hide progress bar after search has finished Dispatcher.BeginInvoke(new Action(() => { ProgramListProgress.Visibility = Visibility.Collapsed; })); }); UpdateThread.Start(); }