Итерации по разделу реестра «SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall», кажется, дают полный список установленных приложений.
Помимо приведенного ниже примера, вы можете найти версию, аналогичную тому, что я сделал здесь .
Это грубый пример, вы, вероятно, захотите что-то сделать, чтобы вырезать пустые строки, как во второй предоставленной ссылке.
string registry_key = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
using(Microsoft.Win32.RegistryKey key = Registry.LocalMachine.OpenSubKey(registry_key))
{
foreach(string subkey_name in key.GetSubKeyNames())
{
using(RegistryKey subkey = key.OpenSubKey(subkey_name))
{
Console.WriteLine(subkey.GetValue("DisplayName"));
}
}
}
В качестве альтернативы вы можете использовать WMI, как уже упоминалось:
ManagementObjectSearcher mos = new ManagementObjectSearcher("SELECT * FROM Win32_Product");
foreach(ManagementObject mo in mos.Get())
{
Console.WriteLine(mo["Name"]);
}
Но это довольно медленное выполнение, и я слышал, что он может отображать только программы, установленные в разделе «ALLUSERS», хотя это может быть неверно. Он также игнорирует компоненты и обновления Windows, которые могут быть вам полезны.
Вы можете взглянуть на эту статью . Он использует реестр для чтения списка установленных приложений.
public void GetInstalledApps() { string uninstallKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"; using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(uninstallKey)) { foreach (string skName in rk.GetSubKeyNames()) { using (RegistryKey sk = rk.OpenSubKey(skName)) { try { lstInstalled.Items.Add(sk.GetValue("DisplayName")); } catch (Exception ex) { } } } } }
источник
Я согласен, что лучше всего использовать раздел реестра.
Обратите внимание , однако, что указанный ключ
@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
, будет перечислять все приложения в 32-битной установке Windows и 64-битные приложения в 64-битной установке Windows.Чтобы также видеть 32-разрядные приложения, установленные в 64-разрядной версии Windows, вам также потребуется перечислить ключ
@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
.источник
regedit
это так кажется. Однако в 32-битной программе (в 64-битной Windows) оба списка идентичныWOW6432Node
списку изregedit
.Я хотел иметь возможность извлекать список приложений так, как они отображаются в меню «Пуск». Используя реестр, я получал записи, которые не отображались в меню «Пуск».
Я также хотел найти путь к exe и извлечь значок, чтобы в конечном итоге сделать красивую программу запуска. К сожалению, с методом реестра это своего рода хит и промах, поскольку мои наблюдения показывают, что эта информация не является надежной.
Моя альтернатива основана на оболочке: AppsFolder, к которой вы можете получить доступ, запустив ее,
explorer.exe shell:appsFolder
и в которой перечислены все приложения, включая приложения магазина, которые в настоящее время установлены и доступны через меню «Пуск». Проблема в том, что это виртуальная папка, к которой нельзя получить доступSystem.IO.Directory
. Вместо этого вам придется использовать собственные команды shell32. К счастью, Microsoft опубликовала Microsoft.WindowsAPICodePack-Shell на Nuget, которая является оболочкой для вышеупомянутых команд. Достаточно сказать, вот код:// GUID taken from https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid var FOLDERID_AppsFolder = new Guid("{1e87508d-89c2-42f0-8a7e-645a0f50ca58}"); ShellObject appsFolder = (ShellObject)KnownFolderHelper.FromKnownFolderId(FOLDERID_AppsFolder); foreach (var app in (IKnownFolder)appsFolder) { // The friendly app name string name = app.Name; // The ParsingName property is the AppUserModelID string appUserModelID = app.ParsingName; // or app.Properties.System.AppUserModel.ID // You can even get the Jumbo icon in one shot ImageSource icon = app.Thumbnail.ExtraLargeBitmapSource; }
Вот и все. Вы также можете запускать приложения, используя
System.Diagnostics.Process.Start("explorer.exe", @" shell:appsFolder\" + appModelUserID);
Это работает для обычных приложений Win32 и приложений магазина UWP. Как насчет яблок.
Поскольку вы заинтересованы в перечислении всех установленных приложений, разумно ожидать, что вы, возможно, захотите отслеживать новые или удаленные приложения, что вы можете сделать с помощью
ShellObjectWatcher
:ShellObjectWatcher sow = new ShellObjectWatcher(appsFolder, false); sow.AllEvents += (s, e) => DoWhatever(); sow.Start();
Изменить: также может быть интересно узнать, что упомянутый выше AppUserMoedlID - это уникальный идентификатор, который Windows использует для группировки окон на панели задач .
источник
AllEvents
таких , какItemCreated
илиItemRenamed
который я пытался использовать , чтобы следить за приложениями , как они были установлены или удалены. Аргументы этих событий содержатPath
свойство, но это свойство всегда имеет значение null, по крайней мере, в моих тестах. Я не стал пытаться выяснить, как получить из него имя синтаксического анализа, поскольку оно всегда равно null. Вместо этого я просто храню список приложений, которые синхронизирую всякий раз, когда возникает элемент, путем итерации по приложениям в папке. Не идеально, но выполняет свою работу.Стоит отметить, что класс Win32_Product WMI представляет продукты, установленные установщиком Windows . не каждое приложение использует установщик Windows
однако "SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall" представляет приложения для 32-битной версии. Для 64-битной версии вам также необходимо пройти через "HKEY_LOCAL_MACHINE \ SOFTWARE \ Wow6432Node \ Microsoft \ Windows \ CurrentVersion \ Uninstall", и, поскольку не у каждого программного обеспечения есть 64-битная версия, все установленные приложения представляют собой объединение ключей в обоих местах, которые имеют "UninstallString" Цени с ними.
но лучшие варианты остаются теми же. поперечные ключи реестра - лучший подход, так как каждое приложение имеет запись в реестре [включая те, что находятся в установщике Windows]. однако метод реестра небезопасен, так как если кто-то удалит соответствующий ключ, вы не узнаете Напротив, изменение HKEY_Classes_ROOT \ Installers сложнее, так как оно связано с проблемами лицензирования, такими как Microsoft Office или другие продукты. для более надежного решения вы всегда можете комбинировать альтернативный реестр с WMI.
источник
Хотя принятое решение работает, оно не является полным. Безусловно.
Если вы хотите получить все ключи, вам нужно учесть еще 2 вещи:
и
Имея это в виду, мне удалось получить ВСЕ установленные приложения, используя следующий код, БЕЗ использования WMI
Вот код:
List<string> installs = new List<string>(); List<string> keys = new List<string>() { @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall" }; // The RegistryView.Registry64 forces the application to open the registry as x64 even if the application is compiled as x86 FindInstalls(RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64), keys, installs); FindInstalls(RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64), keys, installs); installs = installs.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToList(); installs.Sort(); // The list of ALL installed applications private void FindInstalls(RegistryKey regKey, List<string> keys, List<string> installed) { foreach (string key in keys) { using (RegistryKey rk = regKey.OpenSubKey(key)) { if (rk == null) { continue; } foreach (string skName in rk.GetSubKeyNames()) { using (RegistryKey sk = rk.OpenSubKey(skName)) { try { installed.Add(Convert.ToString(sk.GetValue("DisplayName"))); } catch (Exception ex) { } } } } } }
источник
Пройдитесь по ключам «HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall» и проверьте их значения «DisplayName».
источник
Используйте Windows Installer API!
Это позволяет производить надежное перечисление всех программ. Реестр ненадежен, но WMI тяжеловесен.
источник
Объект для списка:
public class InstalledProgram { public string DisplayName { get; set; } public string Version { get; set; } public string InstalledDate { get; set; } public string Publisher { get; set; } public string UnninstallCommand { get; set; } public string ModifyPath { get; set; } }
Призыв к созданию списка:
List<InstalledProgram> installedprograms = new List<InstalledProgram>(); string registry_key = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"; using (RegistryKey key = Registry.LocalMachine.OpenSubKey(registry_key)) { foreach (string subkey_name in key.GetSubKeyNames()) { using (RegistryKey subkey = key.OpenSubKey(subkey_name)) { if (subkey.GetValue("DisplayName") != null) { installedprograms.Add(new InstalledProgram { DisplayName = (string)subkey.GetValue("DisplayName"), Version = (string)subkey.GetValue("DisplayVersion"), InstalledDate = (string)subkey.GetValue("InstallDate"), Publisher = (string)subkey.GetValue("Publisher"), UnninstallCommand = (string)subkey.GetValue("UninstallString"), ModifyPath = (string)subkey.GetValue("ModifyPath") }); } } } }
источник
Как указывали другие, принятый ответ не возвращает установки как x86, так и x64. Ниже мое решение для этого. Он создает
StringBuilder
, добавляет к нему значения реестра (с форматированием) и записывает свой вывод в текстовый файл:const string FORMAT = "{0,-100} {1,-20} {2,-30} {3,-8}\n"; private void LogInstalledSoftware() { var line = string.Format(FORMAT, "DisplayName", "Version", "Publisher", "InstallDate"); line += string.Format(FORMAT, "-----------", "-------", "---------", "-----------"); var sb = new StringBuilder(line, 100000); ReadRegistryUninstall(ref sb, RegistryView.Registry32); sb.Append($"\n[64 bit section]\n\n{line}"); ReadRegistryUninstall(ref sb, RegistryView.Registry64); File.WriteAllText(@"c:\temp\log.txt", sb.ToString()); } private static void ReadRegistryUninstall(ref StringBuilder sb, RegistryView view) { const string REGISTRY_KEY = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"; using var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, view); using var subKey = baseKey.OpenSubKey(REGISTRY_KEY); foreach (string subkey_name in subKey.GetSubKeyNames()) { using RegistryKey key = subKey.OpenSubKey(subkey_name); if (!string.IsNullOrEmpty(key.GetValue("DisplayName") as string)) { var line = string.Format(FORMAT, key.GetValue("DisplayName"), key.GetValue("DisplayVersion"), key.GetValue("Publisher"), key.GetValue("InstallDate")); sb.Append(line); } key.Close(); } subKey.Close(); baseKey.Close(); }
источник
Лучше всего использовать WMI . В частности, класс Win32_Product .
источник
Могу я предложить вам взглянуть на WMI ( инструментарий управления Windows ). Если вы добавите ссылку на System.Management в свой проект C #, вы получите доступ к классу ManagementObjectSearcher, который, вероятно, окажется для вас полезным.
Существуют различные классы WMI для установленных приложений , но если он был установлен с помощью установщика Windows, то, вероятно, вам лучше всего подходит класс Win32_Product.
ManagementObjectSearcher s = new ManagementObjectSearcher("SELECT * FROM Win32_Product");
источник
Я использовал подход Nicks - мне нужно было проверить, установлены ли Remote Tools для Visual Studio или нет, это кажется немного медленным, но в отдельном потоке для меня это нормально. - вот мой расширенный код:
private bool isRdInstalled() { ManagementObjectSearcher p = new ManagementObjectSearcher("SELECT * FROM Win32_Product"); foreach (ManagementObject program in p.Get()) { if (program != null && program.GetPropertyValue("Name") != null && program.GetPropertyValue("Name").ToString().Contains("Microsoft Visual Studio 2012 Remote Debugger")) { return true; } if (program != null && program.GetPropertyValue("Name") != null) { Trace.WriteLine(program.GetPropertyValue("Name")); } } return false; }
источник
Мое требование - проверить, установлено ли в моей системе определенное программное обеспечение. Это решение работает, как ожидалось. Это может тебе помочь. Я использовал приложение Windows на C # с Visual Studio 2015.
private void Form1_Load(object sender, EventArgs e) { object line; string softwareinstallpath = string.Empty; string registry_key = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"; using (var baseKey = Microsoft.Win32.RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)) { using (var key = baseKey.OpenSubKey(registry_key)) { foreach (string subkey_name in key.GetSubKeyNames()) { using (var subKey = key.OpenSubKey(subkey_name)) { line = subKey.GetValue("DisplayName"); if (line != null && (line.ToString().ToUpper().Contains("SPARK"))) { softwareinstallpath = subKey.GetValue("InstallLocation").ToString(); listBox1.Items.Add(subKey.GetValue("InstallLocation")); break; } } } } } if(softwareinstallpath.Equals(string.Empty)) { MessageBox.Show("The Mirth connect software not installed in this system.") } string targetPath = softwareinstallpath + @"\custom-lib\"; string[] files = System.IO.Directory.GetFiles(@"D:\BaseFiles"); // Copy the files and overwrite destination files if they already exist. foreach (var item in files) { string srcfilepath = item; string fileName = System.IO.Path.GetFileName(item); System.IO.File.Copy(srcfilepath, targetPath + fileName, true); } return; }
источник