我读了很多的获取程序的信息。 算法并没有做我想做的。 我需要安装的程序完全一样的控制面板。
所以我用:
- WMI
Win32_Product
类。 这表明只有MSI安装程序。 - 注册表项。
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
。 此外,某些程序不能在控制面板中显示,有些程序在此注册表节点显示在控制面板中没有。
那么,有没有人在这个世界上,谁知道哪种算法使用控制面板显示已安装的程序?
UPD1:是的,我用64位的,我知道有64位安装的程序 “HKLM \ SOFTWARE \ Wow6432Node \微软\的Windows \ CurrentVersion \卸载” 的另一个节点,但下面的代码枚举twise HKLM \ SOFTWARE \ Wow6432Node \微软\的Windows \ CURRENTVERSION \卸载部分,奇怪...
VAR程序=新名单(); 串registry_key = @ “SOFTWARE \微软\的Windows \ CurrentVersion \卸载”; 使用(Microsoft.Win32.RegistryKey键= Registry.LocalMachine.OpenSubKey(registry_key)) { 的foreach(在key.GetSubKeyNames串subkey_name()) { 使用(的RegistryKey子项= key.OpenSubKey(subkey_name)) { 变种名称=(字符串)subkey.GetValue( “显示名称”); 如果(!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 { 常量字符串registry_key = @ “SOFTWARE \微软\的Windows \ CurrentVersion \卸载”;
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开始#,所以我不知道的方式通过所有四个REG位置环,所以我有两个循环(一个用于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的答案是足以满足大多数的目的 - 我在我的名单VS在程序和功能143有144项。 审查 ,他的解决办法是打这些注册表位置:
- HKLM \ SOFTWARE \微软\的Windows \ CurrentVersion \卸载
- HKCU \软件\微软\的Windows \ CurrentVersion \卸载
- HKLM \ SOFTWARE \ Wow6432Node \微软\的Windows \ CurrentVersion \卸载
要获得资格,每个子项必须具备:
且不得有:
- 所述SystemComponent REG_DWORD(非零)
- 该ParentKeyName或ParentDisplayName REG_SZ值
- 该ReleaseType REG_SZ值
在一个addtional增强我发现是Windows安装程序项,定义为:
- 键名是一个标准的GUID字符串
- 该WindowsInstaller REG_DWORD存在(和非零)
对于这样的项目,您可以使用从MSI.DLL Win32函数MsiGetProductInfoW,并要求由键所代表的GUID的“VERSIONSTRING”属性的额外步骤。
如果这个函数返回1605:ERROR_UNKNOWN_PRODUCT,这意味着该条目不按照Windows安装程序安装,并应显示被排除在外。
实施这一小调整之后,我的名单现在相同的程序和功能。
在其他几个答案在这里讨论的SystemComponent注册表项通常是0或1。然而可能值的REG_DWORD,我看到一对夫妇的实例(如微软的Visio 2010和Microsoft Project 2010),其中SystemComponent是REG_SZ没有数据。 这蒙上SystemComponent为int的任何解决方案因此容易抛出一个异常,在这些情况下。
文章来源: C#: How to get installing programs exactly like in control panel programs and features?