Wie werden die Anwendungen mithilfe von C # -Code im System installiert?
quelle
Wie werden die Anwendungen mithilfe von C # -Code im System installiert?
Das Durchlaufen des Registrierungsschlüssels "SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall" scheint eine umfassende Liste der installierten Anwendungen zu ergeben.
Abgesehen von dem folgenden Beispiel finden Sie eine ähnliche Version wie hier .
Dies ist ein grobes Beispiel. Sie möchten wahrscheinlich etwas tun, um leere Zeilen wie im zweiten bereitgestellten Link zu entfernen.
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"));
}
}
}
Alternativ können Sie WMI wie folgt verwenden:
ManagementObjectSearcher mos = new ManagementObjectSearcher("SELECT * FROM Win32_Product");
foreach(ManagementObject mo in mos.Get())
{
Console.WriteLine(mo["Name"]);
}
Die Ausführung ist jedoch etwas langsamer, und ich habe gehört, dass möglicherweise nur unter "ALLUSERS" installierte Programme aufgelistet werden, obwohl dies möglicherweise falsch ist. Außerdem werden die Windows-Komponenten und -Updates ignoriert, die für Sie nützlich sein können.
Sie können sich diesen Artikel ansehen . Es verwendet die Registrierung, um die Liste der installierten Anwendungen zu lesen.
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) { } } } } }
quelle
Ich bin damit einverstanden, dass die Aufzählung über den Registrierungsschlüssel der beste Weg ist.
Beachten Sie jedoch, dass der angegebene Schlüssel
@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
alle Anwendungen in einer 32-Bit-Windows-Installation und 64-Bit-Anwendungen in einer Windows 64-Bit-Installation auflistet.Um auch 32-Bit-Anwendungen zu sehen, die in einer Windows 64-Bit-Installation installiert sind, müssen Sie auch den Schlüssel aufzählen
@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
.quelle
regedit
scheint es so. In einem 32 - Bit - Programm (auf 64 - Bit - Windows) sind jedoch beide Listen identisch mit demWOW6432Node
einem ausregedit
.Ich wollte in der Lage sein, eine Liste von Apps so zu extrahieren, wie sie im Startmenü angezeigt werden. Bei Verwendung der Registrierung wurden Einträge angezeigt, die nicht im Startmenü angezeigt werden.
Ich wollte auch den exe-Pfad finden und ein Symbol extrahieren, um schließlich einen gut aussehenden Launcher zu erstellen. Leider ist dies bei der Registrierungsmethode ein Hit und Miss, da ich feststelle, dass diese Informationen nicht zuverlässig verfügbar sind.
Meine Alternative basiert auf der Shell: AppsFolder, auf den Sie durch Ausführen zugreifen können
explorer.exe shell:appsFolder
und der alle Apps auflistet, einschließlich Store-Apps, die derzeit installiert sind und über das Startmenü verfügbar sind. Das Problem ist, dass dies ein virtueller Ordner ist, auf den nicht zugegriffen werden kannSystem.IO.Directory
. Stattdessen müssten Sie native Shell32-Befehle verwenden. Glücklicherweise hat Microsoft die Microsoft.WindowsAPICodePack-Shell auf Nuget veröffentlicht, einem Wrapper für die oben genannten Befehle. Genug gesagt, hier ist der Code:// 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; }
Und das ist alles. Sie können die Apps auch mit starten
System.Diagnostics.Process.Start("explorer.exe", @" shell:appsFolder\" + appModelUserID);
Dies funktioniert für reguläre Win32-Apps und UWP-Store-Apps. Wie wäre es mit Äpfeln?
Da Sie daran interessiert sind, alle installierten Apps aufzulisten, ist zu erwarten, dass Sie auch nach neuen Apps oder deinstallierten Apps suchen möchten. Dies können Sie tun, indem Sie
ShellObjectWatcher
:ShellObjectWatcher sow = new ShellObjectWatcher(appsFolder, false); sow.AllEvents += (s, e) => DoWhatever(); sow.Start();
Bearbeiten: Möglicherweise möchten Sie auch wissen, dass die oben erwähnte AppUserMoedlID die eindeutige ID ist, die Windows zum Gruppieren von Fenstern in der Taskleiste verwendet .
quelle
AllEvents
wieItemCreated
oderItemRenamed
wo ich versuchte , mit Spur von Anwendungen zu halten , wie sie installiert oder entfernt wurden. Die Ereignisargumente dieser Ereignisse enthalten einePath
Eigenschaft, aber diese Eigenschaft ist zumindest in meinen Tests immer null. Ich habe mich nicht darum gekümmert, herauszufinden, wie man einen Parsing-Namen daraus erhält, da sie immer null ist. Stattdessen behalte ich einfach eine Liste von Apps, die ich synchronisiere, wenn ein Element ausgelöst wird, indem ich die Apps im Ordner durchlaufe. Nicht ideal, aber erledigt den Job.Es ist erwähnenswert, dass die WMI-Klasse Win32_Product Produkte darstellt, wie sie von Windows Installer installiert werden . Nicht jede Anwendung verwendet das Windows-Installationsprogramm
"SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall" steht jedoch für 32-Bit-Anwendungen. Für 64-Bit müssen Sie außerdem "HKEY_LOCAL_MACHINE \ SOFTWARE \ Wow6432Node \ Microsoft \ Windows \ CurrentVersion \ Uninstall" durchlaufen. Da nicht jede Software eine 64-Bit-Version hat, sind die insgesamt installierten Anwendungen eine Vereinigung von Schlüsseln an beiden Speicherorten mit "UninstallString". Wert mit ihnen.
Die besten Optionen bleiben jedoch die gleichen. Traverse-Registrierungsschlüssel sind ein besserer Ansatz, da jede Anwendung einen Eintrag in der Registrierung hat [einschließlich derjenigen in Windows Installer]. Die Registrierungsmethode ist jedoch unsicher, als ob jemand den entsprechenden Schlüssel entfernt, dann wissen Sie es nicht Der Anwendungseintrag. Im Gegenteil, das Ändern der HKEY_Classes_ROOT \ Installers ist schwieriger, da es mit Lizenzproblemen wie Microsoft Office oder anderen Produkten verbunden ist. Für eine robustere Lösung können Sie die Registrierungsalternative immer mit der WMI kombinieren.
quelle
Die akzeptierte Lösung funktioniert zwar, ist jedoch nicht vollständig. Bei weitem.
Wenn Sie alle Schlüssel erhalten möchten, müssen Sie zwei weitere Dinge berücksichtigen:
und
In diesem Sinne habe ich es geschafft, ALLE installierten Anwendungen mit dem folgenden Code OHNE zu erhalten WMI zu verwenden
Hier ist der Code:
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) { } } } } } }
quelle
Durchlaufen Sie die Schlüssel "HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall" und überprüfen Sie deren "DisplayName" -Werte.
quelle
Verwenden Sie die Windows Installer-API!
Es ermöglicht eine zuverlässige Aufzählung aller Programme. Die Registrierung ist nicht zuverlässig, aber WMI ist schwergewichtig.
quelle
Das Objekt für die Liste:
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; } }
Der Aufruf zum Erstellen der Liste:
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") }); } } } }
quelle
Wie andere bereits betont haben, gibt die akzeptierte Antwort nicht sowohl x86- als auch x64-Installationen zurück. Unten ist meine Lösung dafür. Es erstellt ein
StringBuilder
, hängt die Registrierungswerte an (mit Formatierung) an und schreibt seine Ausgabe in eine Textdatei: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(); }
quelle
Am besten verwenden Sie WMI . Insbesondere die Win32_Product- Klasse.
quelle
Könnte ich vorschlagen, dass Sie sich WMI ( Windows Management Instrumentation) ansehen ) . Wenn Sie Ihrem C # -Projekt den System.Management-Verweis hinzufügen, erhalten Sie Zugriff auf die Klasse "ManagementObjectSearcher", die Sie wahrscheinlich nützlich finden werden.
Es gibt verschiedene WMI-Klassen für installierte Anwendungen . Wenn sie jedoch mit Windows Installer installiert wurden, ist die Win32_Product-Klasse wahrscheinlich am besten für Sie geeignet.
ManagementObjectSearcher s = new ManagementObjectSearcher("SELECT * FROM Win32_Product");
quelle
Ich habe den Nicks-Ansatz verwendet. Ich musste überprüfen, ob die Remote Tools für Visual Studio installiert sind oder nicht. Es scheint etwas langsam zu sein, aber in einem separaten Thread ist dies für mich in Ordnung. - hier mein erweiterter Code:
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; }
quelle
Ich muss überprüfen, ob auf meinem System bestimmte Software installiert ist. Diese Lösung funktioniert wie erwartet. Es könnte dir helfen. Ich habe eine Windows-Anwendung in c # mit Visual Studio 2015 verwendet.
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; }
quelle