Überprüfen Sie, ob die Anwendung in der Registrierung installiert ist
Lesezeit: 11 Minuten
Hyperion
Im Moment verwende ich dies, um alle Anwendungen aufzulisten, die in der Registrierung für 32-Bit und 64 aufgeführt sind. Ich habe die anderen Beispiele gesehen, wie man ohne Erfolg überprüft, ob eine Anwendung installiert ist.
string registryKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
RegistryKey key = Registry.LocalMachine.OpenSubKey(registryKey);
if (key != null)
{
foreach (String a in key.GetSubKeyNames())
{
RegistryKey subkey = key.OpenSubKey(a);
Console.WriteLine(subkey.GetValue("DisplayName"));
}
}
registryKey = @"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall";
key = Registry.LocalMachine.OpenSubKey(registryKey);
if (key != null)
{
foreach (String a in key.GetSubKeyNames())
{
RegistryKey subkey = key.OpenSubKey(a);
Console.WriteLine(subkey.GetValue("DisplayName"));
}
}
Dieser Ausschnitt listet also alles im Konsolenfenster auf, und was ich versuche, ist, nur einen Programmtitel aus der Liste der Anzeigenamen zu finden, um zu sehen, ob er installiert ist.
Das letzte, was ich versuchte, war
if (subkey.Name.Contains("OpenSSL"))
Console.Writeline("OpenSSL Found");
else
Console.Writeline("OpenSSL Not Found");
Alles, was ich versuchte, kam entweder falsch oder falsch positiv zurück. Kann mir jemand zeigen, wie ich einfach einen Titel aus der Liste holen kann?
Bitte veröffentlichen Sie nicht die bekannte private statische void IsApplicationInstalled(p_name)-Funktion. Es funktioniert bei mir überhaupt nicht.
Als Nebenbemerkung: Sie müssen Close() die Regkeys, die Sie haben Opened()‘d .. obwohl dies verwalteter Code ist, handelt es sich um nicht verwaltete Ressourcen, die auslaufen, wenn Sie sie nicht schließen.
– Canhazbits
4. Mai 2013 um 21:32 Uhr
Vielen Dank für die FYI dazu.
– Hyperions
4. Mai 2013 um 21:34 Uhr
Das klingt, als könnte es ganz nützlich sein. Je nachdem, wofür Sie es verwenden möchten, ist es jedoch möglicherweise besser, den installierten Code an die jeweilige Anwendung anzupassen, damit er schneller ausgeführt wird.
– Sildoreth
16. Juni 2014 um 21:15 Uhr
Außerdem werden nicht alle Programme in der “Deinstallationsliste” registriert. Nur zur Info.
– Sildoreth
16. Juni 2014 um 21:17 Uhr
Hyperion
Nach der Suche und Fehlerbehebung habe ich es so zum Laufen gebracht:
public static bool checkInstalled (string c_name)
{
string displayName;
string registryKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
RegistryKey key = Registry.LocalMachine.OpenSubKey(registryKey);
if (key != null)
{
foreach (RegistryKey subkey in key.GetSubKeyNames().Select(keyName => key.OpenSubKey(keyName)))
{
displayName = subkey.GetValue("DisplayName") as string;
if (displayName != null && displayName.Contains(c_name))
{
return true;
}
}
key.Close();
}
registryKey = @"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall";
key = Registry.LocalMachine.OpenSubKey(registryKey);
if (key != null)
{
foreach (RegistryKey subkey in key.GetSubKeyNames().Select(keyName => key.OpenSubKey(keyName)))
{
displayName = subkey.GetValue("DisplayName") as string;
if (displayName != null && displayName.Contains(c_name))
{
return true;
}
}
key.Close();
}
return false;
}
Und ich nenne es einfach nur mit
if(checkInstalled("Application Name"))
Diese Lösung wird nicht immer funktionieren, da nicht alle Einträge immer menschenlesbare Namen sind, die meisten Einträge sind GUIDs, dann müssen Sie überprüfen, welche Anwendung diese GUID darstellt
– feldeOne
19. September 2018 um 12:45 Uhr
@feldeOne Zu dieser Zeit diente dieser Code nur dazu, zu überprüfen, ob bestimmte Anwendungen mit angegebenen Ordnernamen installiert wurden
– Hyperions
20. September 2018 um 14:17 Uhr
@feldeOne es funktioniert nicht, wenn ich die Anwendung deinstalliere. Es zeigt immer noch, dass es auf meiner CPU liegt.
– Mattenratte
17. April 2020 um 8:41 Uhr
Das Problem ist, wenn Sie eine 32-Bit-Anwendung ausführen, werden 32-Bit-Programme zurückgegeben, wenn es 64-Bit sein sollte.
– Silny ToJa
7. Mai 2020 um 12:11 Uhr
Dies ist eine saubere Möglichkeit, dies ohne so viel Code zu tun.
dotnet fügen Sie das Paket Microsoft.Win32.Registry für diejenigen hinzu, die dies in dotnet standard/core benötigen
– jb007
13. Juni 2019 um 17:35 Uhr
Dieser Code muss als X64 ausgeführt werden oder in der Build-Einstellung des Projekts die Option „32-Bit bevorzugen“ deaktivieren.
– Shanghai
31. Oktober 2019 um 23:05 Uhr
Mrocny Arturek
Ich habe den Code von @Stellan Lindell überprüft und er funktioniert nicht in allen Fällen. Meine Version sollte in allen Szenarien funktionieren und überprüft die spezifische Version der installierten Programme (x86, x64).
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Win32;
namespace Test
{
internal class Program
{
public enum ProgramVersion
{
x86,
x64
}
private static IEnumerable<string> GetRegisterSubkeys(RegistryKey registryKey)
{
return registryKey.GetSubKeyNames()
.Select(registryKey.OpenSubKey)
.Select(subkey => subkey.GetValue("DisplayName") as string);
}
private static bool CheckNode(RegistryKey registryKey, string applicationName, ProgramVersion? programVersion)
{
return GetRegisterSubkeys(registryKey).Any(displayName => displayName != null
&& displayName.Contains(applicationName)
&& displayName.Contains(programVersion.ToString()));
}
private static bool CheckApplication(string registryKey, string applicationName, ProgramVersion? programVersion)
{
RegistryKey key = Registry.LocalMachine.OpenSubKey(registryKey);
if (key != null)
{
if (CheckNode(key, applicationName, programVersion))
return true;
key.Close();
}
return false;
}
public static bool IsSoftwareInstalled(string applicationName, ProgramVersion? programVersion)
{
string[] registryKey = new [] {
@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
@"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
};
return registryKey.Any(key => CheckApplication(key, applicationName, programVersion));
}
private static void Main()
{
// Examples
Console.WriteLine("Notepad++: " + IsSoftwareInstalled("Notepad++", null));
Console.WriteLine("Notepad++(x86): " + IsSoftwareInstalled("Notepad++", ProgramVersion.x86));
Console.WriteLine("Notepad++(x64): " + IsSoftwareInstalled("Notepad++", ProgramVersion.x64));
Console.WriteLine("Microsoft Visual C++ 2009: " + IsSoftwareInstalled("Microsoft Visual C++ 2009", null));
Console.WriteLine("Microsoft Visual C-- 2009: " + IsSoftwareInstalled("Microsoft Visual C-- 2009", null));
Console.WriteLine("Microsoft Visual C++ 2013: " + IsSoftwareInstalled("Microsoft Visual C++ 2013", null));
Console.WriteLine("Microsoft Visual C++ 2012 Redistributable (x86): " + IsSoftwareInstalled("Microsoft Visual C++ 2013", ProgramVersion.x86));
Console.WriteLine("Microsoft Visual C++ 2012 Redistributable (x64): " + IsSoftwareInstalled("Microsoft Visual C++ 2013", ProgramVersion.x64));
Console.ReadKey();
}
}
}
Mit diesem Code kann ich Notepad++ 32bit auf meinem Computer erkennen, aber nicht Notepad++ 64bit auf einem anderen Computer. Übrigens ist der Code durch die Nestling-Methode wirklich schwer lesbar
– Willkommen
17. September 2019 um 20:02 Uhr
ok, grund gefunden. 32-Bit-Anwendung benötigt eine Problemumgehung für die Suche nach installierten 64-Bit-Anwendungen
– Willkommen
18. September 2019 um 17:34 Uhr
Die Lösung @Hyperion ist in Ordnung, aber sie hat einen Fehler, weil für 32-Bit-Konfigurationen. Es werden keine 64-Bit-Register zurückgegeben. Gehen Sie wie folgt vor, um 64-Bit-Register zu empfangen:
Die oben genannten Lösungen sind wirklich gut, aber manchmal müssen Sie überprüfen, ob das Produkt auch auf einem anderen Computer installiert ist. Es gibt also eine Version, die auf den obigen Lösungen von @Stellan Lindell und @Mroczny Arturek basiert
Diese Methode funktioniert für den lokalen Computer und auch für den Remote-Computer.
public static bool IsSoftwareInstalled(string softwareName, string remoteMachine = null, StringComparison strComparison = StringComparison.Ordinal)
{
string uninstallRegKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
RegistryView[] enumValues = (RegistryView[])Enum.GetValues(typeof(RegistryView));
//Starts from 1, because first one is Default, so we dont need it...
for (int i = 1; i < enumValues.Length; i++)
{
//This one key is all what we need, because RegView will do the rest for us
using (RegistryKey key = (string.IsNullOrWhiteSpace(remoteMachine))
? RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, enumValues[i]).OpenSubKey(uninstallRegKey)
: RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, remoteMachine, enumValues[i]).OpenSubKey(uninstallRegKey))
{
if (key != null)
{
if (key.GetSubKeyNames()
.Select(keyName => key.OpenSubKey(keyName))
.Select(subKey => subKey.GetValue("DisplayName") as string)
//SomeTimes we really need the case sensitive/insensitive option...
.Any(displayName => displayName != null && displayName.IndexOf(softwareName, strComparison) >= 0))
{ return true; }
}
}
}
return false;
}
Die Registrierungsversion ist nur eine von zwei Standardoptionen. Eine andere Option ist die Verwendung von WMI, aber die Registrierungsversion ist aufgrund der Leistung viel besser, also nehmen Sie nur WMI als Alternative.
//This one does't have a case sensitive/insesitive option, but if you need it, just don't use LIKE %softwareName%
//and get all products (SELECT Name FROM Win32_Product). After that just go trough the result and compare...
public static bool IsSoftwareInstalledWMI(string softwareName, string remoteMachine = null)
{
string wmiPath = (!string.IsNullOrEmpty(remoteMachine))
? @"\\" + remoteMachine + @"\root\cimv2"
: @"\\" + Environment.MachineName + @"\root\cimv2";
SelectQuery select = new SelectQuery(string.Format("SELECT * FROM Win32_Product WHERE Name LIKE \"%{0}%\"", softwareName));
if (SelectStringsFromWMI(select, new ManagementScope(wmiPath)).Count > 0) { return true; }
return false;
}
Es gibt meine SelectStringsFromWMI-Methode, aber Sie können dies selbst tun, dies ist kein wichtiger Teil dieser Lösung. Aber falls es dich interessiert, hier ist es…
public static List<Dictionary<string, string>> SelectStringsFromWMI(SelectQuery select, ManagementScope wmiScope)
{
List<Dictionary<string, string>> result = new List<Dictionary<string, string>>();
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(wmiScope, select))
{
using (ManagementObjectCollection objectCollection = searcher.Get())
{
foreach (ManagementObject managementObject in objectCollection)
{
//With every new object we add new Dictionary
result.Add(new Dictionary<string, string>());
foreach (PropertyData property in managementObject.Properties)
{
//Always add data to newest Dictionary
result.Last().Add(property.Name, property.Value?.ToString());
}
}
return result;
}
}
}
!!AKTUALISIEREN!!
Aufgrund der wirklich schlechten Leistung gibt es eine weitere Verbesserung. Holen Sie sich einfach die Werte asynchron.
public static bool IsSoftwareInstalled(string softwareName, string remoteMachine = null, StringComparison strComparison = StringComparison.Ordinal)
{
string uninstallRegKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
RegistryView[] enumValues = (RegistryView[])Enum.GetValues(typeof(RegistryView));
//Starts from 1, because first one is Default, so we dont need it...
for (int i = 1; i < enumValues.Length; i++)
{
//This one key is all what we need, because RegView will do the rest for us
using (RegistryKey regKey = (string.IsNullOrWhiteSpace(remoteMachine))
? RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, enumValues[i]).OpenSubKey(uninstallRegKey)
: RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, remoteMachine, enumValues[i]).OpenSubKey(uninstallRegKey))
{
if (SearchSubKeysForValue(regKey, "DisplayName", softwareName, strComparison).Result)
{ return true; }
}
}
return false;
}
Und die SearchSubKeysForValue-Methode (kann als Erweiterungsmethode erstellt werden):
public static async Task<bool> SearchSubKeysForValue(RegistryKey regKey, string valueName, string searchedValue, StringComparison strComparison = StringComparison.Ordinal)
{
bool result = false;
string[] subKeysNames = regKey.GetSubKeyNames();
List<Task<bool>> tasks = new List<Task<bool>>();
for (int i = 0; i < subKeysNames.Length - 1; i++)
{
//We have to save current value for i, because we cannot use it in async task due to changed values for it during foor loop
string subKeyName = subKeysNames[i];
tasks.Add(Task.Run(() =>
{
string value = regKey.OpenSubKey(subKeyName)?.GetValue(valueName)?.ToString() ?? null;
return (value != null && value.IndexOf(searchedValue, strComparison) >= 0);
}));
}
bool[] results = await Task.WhenAll(tasks).ConfigureAwait(false);
result = results.Contains(true);
return result;
}
Die ursprüngliche Frage hatte nichts mit entfernten Maschinen zu tun
– Hyperions
20. September 2018 um 14:19 Uhr
@Faded, aber Sie können diese Lösung für lokale und sogar Remote-Computer verwenden. Ja, dies ist eine Lösung für Ihre Antwort mit einigen Verbesserungen. Daher verstehe ich die Ablehnung nicht.
– Blato
21. September 2018 um 6:18 Uhr
@Faded vielleicht wirst du diese aktualisierte Verbesserung mehr zu schätzen wissen … 🙂
– Blato
25. September 2018 um 6:52 Uhr
Willkommen
Ich habe die Lösungen hier ausprobiert, aber sie haben in einigen Fällen nicht funktioniert. Der Grund war, dass mein Programm 32 Bit ist und auf 64 Bit Windows läuft. Mit den hier geposteten Lösungen a 32-Bit-Prozess kann nicht prüfen, ob eine 64-Bit-Anwendung installiert ist.
So greifen Sie mit einem 32-Bit-Prozess auf die 64-Bit-Registrierung zu
public static bool IsSoftwareInstalled(string softwareName)
{
var registryUninstallPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
var registryUninstallPathFor32BitOn64Bit = @"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall";
if (Is32BitWindows())
return IsSoftwareInstalled(softwareName, RegistryView.Registry32, registryUninstallPath);
var is64BitSoftwareInstalled = IsSoftwareInstalled(softwareName, RegistryView.Registry64, registryUninstallPath);
var is32BitSoftwareInstalled = IsSoftwareInstalled(softwareName, RegistryView.Registry64, registryUninstallPathFor32BitOn64Bit);
return is64BitSoftwareInstalled || is32BitSoftwareInstalled;
}
private static bool Is32BitWindows() => Environment.Is64BitOperatingSystem == false;
private static bool IsSoftwareInstalled(string softwareName, RegistryView registryView, string installedProgrammsPath)
{
var uninstallKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, registryView)
.OpenSubKey(installedProgrammsPath);
if (uninstallKey == null)
return false;
return uninstallKey.GetSubKeyNames()
.Select(installedSoftwareString => uninstallKey.OpenSubKey(installedSoftwareString))
.Select(installedSoftwareKey => installedSoftwareKey.GetValue("DisplayName") as string)
.Any(installedSoftwareName => installedSoftwareName != null && installedSoftwareName.Contains(softwareName));
}
Die ursprüngliche Frage hatte nichts mit entfernten Maschinen zu tun
– Hyperions
20. September 2018 um 14:19 Uhr
@Faded, aber Sie können diese Lösung für lokale und sogar Remote-Computer verwenden. Ja, dies ist eine Lösung für Ihre Antwort mit einigen Verbesserungen. Daher verstehe ich die Ablehnung nicht.
– Blato
21. September 2018 um 6:18 Uhr
@Faded vielleicht wirst du diese aktualisierte Verbesserung mehr zu schätzen wissen … 🙂
– Blato
25. September 2018 um 6:52 Uhr
jerryurena
Hier ist meine Version für 64 Bit
public static string[] checkInstalled(string findByName)
{
string[] info = new string[3];
string registryKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
//64 bits computer
RegistryKey key64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
RegistryKey key = key64.OpenSubKey(registryKey);
if (key != null)
{
foreach (RegistryKey subkey in key.GetSubKeyNames().Select(keyName => key.OpenSubKey(keyName)))
{
string displayName = subkey.GetValue("DisplayName") as string;
if (displayName != null && displayName.Contains(findByName))
{
info[0] = displayName;
info[1] = subkey.GetValue("InstallLocation").ToString();
info[2] = subkey.GetValue("Version").ToString();
}
}
key.Close();
}
return info;
}
Sie können diese Methode so aufrufen
string[] JavaVersion = Software.checkInstalled("Java(TM) SE Development Kit");
Wenn das Array leer ist, wurde keine Installation gefunden. Wenn es nicht leer ist, erhalten Sie den ursprünglichen Namen, den relativen Pfad und den Speicherort, was in den meisten Fällen alles ist, was wir erhalten möchten.
13109800cookie-checkÜberprüfen Sie, ob die Anwendung in der Registrierung installiert istyes
Als Nebenbemerkung: Sie müssen
Close()
die Regkeys, die Sie habenOpened()
‘d .. obwohl dies verwalteter Code ist, handelt es sich um nicht verwaltete Ressourcen, die auslaufen, wenn Sie sie nicht schließen.– Canhazbits
4. Mai 2013 um 21:32 Uhr
Vielen Dank für die FYI dazu.
– Hyperions
4. Mai 2013 um 21:34 Uhr
Das klingt, als könnte es ganz nützlich sein. Je nachdem, wofür Sie es verwenden möchten, ist es jedoch möglicherweise besser, den installierten Code an die jeweilige Anwendung anzupassen, damit er schneller ausgeführt wird.
– Sildoreth
16. Juni 2014 um 21:15 Uhr
Außerdem werden nicht alle Programme in der “Deinstallationsliste” registriert. Nur zur Info.
– Sildoreth
16. Juni 2014 um 21:17 Uhr