Wydaje się, że iteracja klucza rejestru „SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall” daje pełną listę zainstalowanych aplikacji.
Oprócz poniższego przykładu możesz znaleźć wersję podobną do tego, co zrobiłem tutaj .
To jest przybliżony przykład, prawdopodobnie będziesz chciał zrobić coś, aby usunąć puste wiersze, jak w drugim podanym łączu.
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"));
}
}
}
Alternatywnie możesz użyć WMI, jak wspomniano:
ManagementObjectSearcher mos = new ManagementObjectSearcher("SELECT * FROM Win32_Product");
foreach(ManagementObject mo in mos.Get())
{
Console.WriteLine(mo["Name"]);
}
Jest to jednak raczej wolniejsze do wykonania i słyszałem, że może wyświetlać tylko programy zainstalowane w „ALLUSERS”, chociaż może to być niepoprawne. Ignoruje również składniki i aktualizacje systemu Windows, które mogą być przydatne.
Możesz rzucić okiem na ten artykuł . Korzysta z rejestru, aby odczytać listę zainstalowanych aplikacji.
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) { } } } } }
źródło
Zgadzam się, że wyliczanie za pomocą klucza rejestru jest najlepszym sposobem.
Należy jednak pamiętać , że podany klucz
@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
wyświetli listę wszystkich aplikacji w 32-bitowej instalacji systemu Windows i 64-bitowych w 64-bitowej instalacji systemu Windows.Aby zobaczyć również aplikacje 32-bitowe zainstalowane w 64-bitowej instalacji systemu Windows, należałoby również wyliczyć klucz
@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
.źródło
regedit
to wygląda. Jednak w programie 32-bitowym (w 64-bitowym systemie Windows) obie listy są identyczne z listamiWOW6432Node
zregedit
.Chciałem mieć możliwość wyodrębnienia listy aplikacji tak, jak pojawiają się w menu Start. Korzystając z rejestru, otrzymywałem wpisy, które nie pojawiają się w menu Start.
Chciałem też znaleźć ścieżkę exe i wyodrębnić ikonę, aby ostatecznie stworzyć ładnie wyglądający program uruchamiający. Niestety, w przypadku metody rejestru jest to trochę chybione, ponieważ z moich obserwacji wynika, że informacje te nie są rzetelnie dostępne.
Moja alternatywa opiera się na powłoce: AppsFolder, do którego można uzyskać dostęp, uruchamiając
explorer.exe shell:appsFolder
i który zawiera listę wszystkich aplikacji, w tym aplikacji sklepu, aktualnie zainstalowanych i dostępnych za pośrednictwem menu Start. Problem polega na tym, że jest to folder wirtualny, do którego nie można uzyskać dostępuSystem.IO.Directory
. Zamiast tego musiałbyś użyć natywnych poleceń shell32. Na szczęście Microsoft opublikował Microsoft.WindowsAPICodePack-Shell na Nuget, który jest opakowaniem dla wyżej wymienionych poleceń. Wystarczy powiedzieć, oto kod:// 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; }
I to wszystko. Możesz także uruchomić aplikacje za pomocą
System.Diagnostics.Process.Start("explorer.exe", @" shell:appsFolder\" + appModelUserID);
Działa to w przypadku zwykłych aplikacji Win32 i aplikacji ze sklepu UWP. A co z tymi jabłkami?
Ponieważ jesteś zainteresowany wyświetleniem wszystkich zainstalowanych aplikacji, rozsądnie jest oczekiwać, że możesz chcieć monitorować nowe aplikacje lub odinstalowane aplikacje, co możesz zrobić za pomocą
ShellObjectWatcher
:ShellObjectWatcher sow = new ShellObjectWatcher(appsFolder, false); sow.AllEvents += (s, e) => DoWhatever(); sow.Start();
Edycja: Można również chcieć wiedzieć, że wspomniany powyżej AppUserMoedlID jest unikalnym identyfikatorem używanym przez system Windows do grupowania okien na pasku zadań .
źródło
AllEvents
takich jakItemCreated
lubItemRenamed
które Próbowałem za pomocą śledzić aplikacje jak zostały one zainstalowane lub usunięte. Argumenty zdarzeń tych zdarzeń zawierająPath
właściwość, ale ta właściwość jest zawsze zerowa, przynajmniej w moich testach. Nie próbowałem dowiedzieć się, jak uzyskać z niej nazwę analizy, ponieważ jest ona zawsze pusta. Zamiast tego po prostu przechowuję listę aplikacji, które synchronizuję za każdym razem, gdy element zostanie podniesiony, iterując po aplikacjach w folderze. Nie jest idealny, ale wykonuje swoją pracę.Warto zauważyć, że klasa WMI Win32_Product reprezentuje produkty, które są instalowane przez Instalatora Windows . nie każda aplikacja korzysta z instalatora Windows
jednakże „SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall” oznacza aplikacje dla wersji 32-bitowej. W przypadku wersji 64-bitowej należy również przejść przez „HKEY_LOCAL_MACHINE \ SOFTWARE \ Wow6432Node \ Microsoft \ Windows \ CurrentVersion \ Uninstall”, a ponieważ nie każde oprogramowanie ma wersję 64-bitową, wszystkie zainstalowane aplikacje to suma kluczy w obu lokalizacjach z opcją „UninstallString” Wartość z nimi.
ale najlepsze opcje pozostają takie same. Traverse klucze rejestru są lepszym podejściem, ponieważ każda aplikacja ma wpis w rejestrze [w tym te w Instalatorze Windows]. jednak metoda rejestru jest niebezpieczna, ponieważ ktoś usunie odpowiedni klucz, nie będziesz wiedział Wręcz przeciwnie, zmiana klucza HKEY_Classes_ROOT \ Installers jest trudniejsza, ponieważ wiąże się z kwestiami licencyjnymi, takimi jak pakiet Microsoft Office lub inne produkty. aby uzyskać bardziej niezawodne rozwiązanie, zawsze możesz połączyć alternatywę rejestru z WMI.
źródło
Chociaż przyjęte rozwiązanie działa, nie jest kompletne. O wiele.
Jeśli chcesz zdobyć wszystkie klucze, musisz wziąć pod uwagę jeszcze 2 rzeczy:
i
Mając to na uwadze, udało mi się pobrać WSZYSTKIE zainstalowane aplikacje przy użyciu poniższego kodu, BEZ korzystania z WMI
Oto kod:
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) { } } } } } }
źródło
Przejdź przez klucze „HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall” i sprawdź ich wartości „DisplayName”.
źródło
Użyj interfejsu API Instalatora Windows!
Pozwala na rzetelne wyliczenie wszystkich programów. Rejestr nie jest wiarygodny, ale WMI jest ciężki.
źródło
Obiekt do listy:
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; } }
Wezwanie do stworzenia listy:
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") }); } } } }
źródło
Jak zauważyli inni, zaakceptowana odpowiedź nie zwraca zarówno instalacji x86, jak i x64. Poniżej znajduje się moje rozwiązanie. Tworzy
StringBuilder
, dołącza do niego wartości rejestru (z formatowaniem) i zapisuje dane wyjściowe do pliku tekstowego: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(); }
źródło
Najlepszym rozwiązaniem jest skorzystanie z WMI . W szczególności klasa Win32_Product .
źródło
Mogę zasugerować przyjrzenie się WMI ( Instrumentacja zarządzania Windows ). Jeśli dodasz odwołanie System.Management do projektu C #, uzyskasz dostęp do klasy `ManagementObjectSearcher ', która prawdopodobnie okaże się przydatna.
Istnieją różne klasy WMI dla zainstalowanych aplikacji , ale jeśli została zainstalowana za pomocą Instalatora Windows, to klasa Win32_Product prawdopodobnie najlepiej Ci odpowiada.
ManagementObjectSearcher s = new ManagementObjectSearcher("SELECT * FROM Win32_Product");
źródło
Użyłem podejścia Nicka - musiałem sprawdzić, czy zdalne narzędzia dla Visual Studio są zainstalowane, czy nie, wydaje się to trochę powolne, ale w osobnym wątku jest to dla mnie w porządku. - tutaj mój rozszerzony kod:
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; }
źródło
Moim wymaganiem jest sprawdzenie, czy w moim systemie jest zainstalowane określone oprogramowanie. To rozwiązanie działa zgodnie z oczekiwaniami. To może ci pomóc. Użyłem aplikacji Windows w języku C # z 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; }
źródło