Как установить приложения в систему с помощью кода c #?
Ответы:
Итерации по разделу реестра «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 вещи:
Приложения x86 и x64 не имеют доступа к одному и тому же реестру. Обычно x86 не может получить доступ к реестру x64. А некоторые приложения регистрируются только в реестре x64.
и
некоторые приложения фактически устанавливаются в реестр CurrentUser вместо LocalMachine
Имея это в виду, мне удалось получить ВСЕ установленные приложения, используя следующий код, БЕЗ использования 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;
}