我读了很多获取计划的信息。 没有algorithm做我想要的。 我需要像控制面板中一样安装程序。
所以我用:
Win32_Product
类。 它只显示msi安装的程序。 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
。 同样,一些程序不显示在控制面板中,一些程序显示在控制面板中而不是在这个registry节点中。 那么,这个世界上有没有人知道哪个algorithm使用控制面板来显示已安装的程序?
UPD1:是的,我使用64位,我知道有64位安装程序的另一个节点“HKLM \ SOFTWARE \ Wow6432Node \微软\的Windows \ CurrentVersion \卸载”,但下面的代码枚举的HKLM \ SOFTWARE \ Wow6432Node \微软\ CurrentVersion \ Uninstall部分,奇怪…
var programs = new List(); string registry_key = @“SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall”; 使用(Microsoft.Win32.RegistryKey key = Registry.LocalMachine.OpenSubKey(registry_key)) { foreach(key.GetSubKeyNames()中的stringsubkey_name) { 使用(RegistryKey subkey = key.OpenSubKey(subkey_name)) { var name =(string)subkey.GetValue(“DisplayName”); 如果(!string.IsNullOrEmpty(名称)) { programs.Add(名称); } } } }
registry_key = @"SOFTWARE\Wow6432Node\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)) { var name = (string)subkey.GetValue("DisplayName"); if (!string.IsNullOrEmpty(name)) { programs.Add(name); } } } } foreach (var program in programs.OrderBy(x => x)) { Console.WriteLine(program); }
好的gyus,我写了类,可以从注册表中安装程序没有修补程序和更新。 它仍然不完全像控制面板,但几乎 。 我希望这可以帮助其他人。
公共静态类InstalledPrograms { const string registry_key = @“SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall”;
public static List<string> GetInstalledPrograms() { var result = new List<string>(); result.AddRange(GetInstalledProgramsFromRegistry(RegistryView.Registry32)); result.AddRange(GetInstalledProgramsFromRegistry(RegistryView.Registry64)); return result; } private static IEnumerable<string> GetInstalledProgramsFromRegistry(RegistryView registryView) { var result = new List<string>(); using (RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, registryView).OpenSubKey(registry_key)) { foreach (string subkey_name in key.GetSubKeyNames()) { using (RegistryKey subkey = key.OpenSubKey(subkey_name)) { if(IsProgramVisible(subkey)) { result.Add((string)subkey.GetValue("DisplayName")); } } } } return result; } private static bool IsProgramVisible(RegistryKey subkey) { var name = (string)subkey.GetValue("DisplayName"); var releaseType = (string)subkey.GetValue("ReleaseType"); //var unistallString = (string)subkey.GetValue("UninstallString"); var systemComponent = subkey.GetValue("SystemComponent"); var parentName = (string)subkey.GetValue("ParentDisplayName"); return !string.IsNullOrEmpty(name) && string.IsNullOrEmpty(releaseType) && string.IsNullOrEmpty(parentName) && (systemComponent == null); } }
我拿了MelnikovI编写的代码(这是超级有用的),并添加了一些东西。 首先,它在注册表中搜索四个地方:
HKLM \ SOFTWARE \微软\的Windows \ CurrentVersion \卸载
HKLM \ SOFTWARE \ Wow6432Node \微软\的Windows \ CurrentVersion \卸载
HKCU \ SOFTWARE \微软\的Windows \ CurrentVersion \卸载
HKCU \ SOFTWARE \ Wow6432Node \微软\的Windows \ CurrentVersion \卸载
它还检查是否有任何子键 – 如果没有,则跳过该键。
最后,它做了一个正则表达式,只允许一组字符[^ a-zA-Z0-9。()+ – ]。
我只是从C#开始,所以我不知道如何循环遍历所有四个注册点,所以我有两个循环(一个用于HKLM,一个用于HKCU)。
public static class InstalledPrograms { public static List<string> GetInstalledPrograms() { var result = new List<string>(); result.AddRange(GetInstalledProgramsFromRegistry(RegistryView.Registry32)); result.AddRange(GetInstalledProgramsFromRegistry(RegistryView.Registry64)); result.Sort(); return result; } private static string cleanText(string dirtyText) { Regex rgx = new Regex("[^a-zA-Z0-9 .()+-]"); string result = rgx.Replace(dirtyText, ""); return result; } private static IEnumerable<string> GetInstalledProgramsFromRegistry(RegistryView registryView) { var result = new List<string>(); List<string> uninstall = new List<string>(); uninstall.Add(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"); uninstall.Add(@"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"); foreach (string registry_key in uninstall) { using (RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, registryView).OpenSubKey(registry_key)) { foreach (string subkey_name in key.GetSubKeyNames()) { using (RegistryKey subkey = key.OpenSubKey(subkey_name)) { if (IsProgramVisible(subkey)) { result.Add(cleanText(subkey.GetValue("DisplayName").ToString()).ToString()); } } } } using (RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, registryView).OpenSubKey(registry_key)) { if (key != null) { foreach (string subkey_name in key.GetSubKeyNames()) { using (RegistryKey subkey = key.OpenSubKey(subkey_name)) { if (IsProgramVisible(subkey)) { result.Add(cleanText(subkey.GetValue("DisplayName").ToString()).ToString()); } } } } } } return result; }
如果有人感兴趣,我将结果与我一直使用的PowerShell进行比较,它们是相同的。
##Get list of Add/Remove programs if (!([Diagnostics.Process]::GetCurrentProcess().Path -match '\\syswow64\\')) { $uninstallPath = "\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" $uninstallWow6432Path = "\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" @( if (Test-Path "HKLM:$uninstallWow6432Path" ) { Get-ChildItem "HKLM:$uninstallWow6432Path"} if (Test-Path "HKLM:$uninstallPath" ) { Get-ChildItem "HKLM:$uninstallPath" } if (Test-Path "HKCU:$uninstallWow6432Path") { Get-ChildItem "HKCU:$uninstallWow6432Path"} if (Test-Path "HKCU:$uninstallPath" ) { Get-ChildItem "HKCU:$uninstallPath" } ) | ForEach-Object { Get-ItemProperty $_.PSPath } | Where-Object { $_.DisplayName -and !$_.SystemComponent -and !$_.ReleaseType -and !$_.ParentKeyName -and ($_.UninstallString -or $_.NoRemove) } | Sort-Object DisplayName | Select-Object DisplayName } else { "You are running 32-bit Powershell on 64-bit system. Please run 64-bit Powershell instead." | Write-Host -ForegroundColor Red }
MelnikovI的答案对于大多数目的已经足够了 – 我的清单中有144个项目,程序和功能中有143个项目。 审查 ,他的解决方案是打这些注册表位置:
为了有资格,每个子项必须有:
并不得有:
我发现的一个附加增强功能是Windows Installer条目,定义如下:
对于这样的条目,您可以采取从msi.dll使用Win32函数MsiGetProductInfoW的附加步骤,并要求由该键表示的GUID的“VersionString”属性。
如果此函数返回1605:ERROR_UNKNOWN_PRODUCT ,则表示该条目未按照Windows Installer安装,应从显示中排除。
执行这个小调整后,我的列表现在与程序和功能相同。