C#:如何得到像控制面板程序和function一样安装程序?

我读了很多获取计划的信息。 没有algorithm做我想要的。 我需要像控制面板中一样安装程序。

所以我用:

  1. WMI Win32_Product类。 它只显示msi安装的程序。
  2. registry项。 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个项目。 审查 ,他的解决方案是打这些注册表位置:

  • HKLM \ SOFTWARE \微软\的Windows \ CurrentVersion \卸载
  • HKCU \软件\微软\的Windows \ CurrentVersion \卸载
  • HKLM \ SOFTWARE \ Wow6432Node \微软\的Windows \ CurrentVersion \卸载

为了有资格,每个子项必须有:

  • DisplayName REG_SZ值

并不得有:

  • SystemComponent REG_DWORD(非零)
  • ParentKeyName或ParentDisplayName REG_SZ值
  • ReleaseType REG_SZ值

我发现的一个附加增强功能是Windows Installer条目,定义如下:

  • 密钥名称是一个标准的GUID字符串
  • WindowsInstaller REG_DWORD存在(并且不为零)

对于这样的条目,您可以采取从msi.dll使用Win32函数MsiGetProductInfoW的附加步骤,并要求由该键表示的GUID的“VersionString”属性。

如果此函数返回1605:ERROR_UNKNOWN_PRODUCT ,则表示该条目未按照Windows Installer安装,应从显示中排除。

执行这个小调整后,我的列表现在与程序和功能相同。